A standard construct in my code is a function that returns a Reader[X,\/[A,B]] and I would like to use the Either portion in a for comprehension, so I have been trying to write a function which will convert a function (X) => \/[A,B] into EitherT[Reader[X,\/[A,B]],A,B].
I can do this with a predetermined Type for X. For instance:
case class Config(host: String)
type ReaderConfig[C] = Reader[Config, C]
type EitherReaderConfig[A,B] = EitherT[ReaderConfig, A,B]
def eitherReaderF[A,B](f: Config => \/[A,B]) : EitherReaderConfig[A,B] = EitherT[ReaderConfig, A,B](Reader[Config, \/[A,B]](f))
eitherReaderF(c => \/-(c.host)).run(Config("hostname"))
However, I am having problems removing the Config type and generalizing over X. This is because EitherT's first argument is expecting one argument in it's type construct: F[_], however Reader is defined as containing 2: Reader[A,B]
One of my attempts is to define a type in terms of an EitherT using type lambdas.
type EitherReaderM[X,A,B] = EitherT[({type λ[α] = Reader[X, α]})#λ, A,B]
def eitherReaderM[X,A,B](f: X => \/[A,B]): EitherReaderM[X,A,B] = EitherT[({type λ[α] = Reader[X, α]})#λ, A,B](Reader(f))
val r: EitherReaderM[Config, Int, String] = eitherReaderM((c: Config) => \/-(c.host))
val run = r.run /// type returns scalaz.Kleisli[[+X]X,Config,scalaz.\/[Int,String]]
run.apply(Config("host")) // fails: value apply is not a member of scalaz.Kleisli[[+X]X,Config,scalaz.\/[Int,String]]
That last bit fails. I feel like I'm close here.....
I'm not entirely sure what's going on yet, but I can run this with 2 calls to run. One on the EitherT and then one on the Kleisli (which I'm not sure where it came in ).
run.run(Config("host"))
However, even though this runs in the console, it doesn't actually compile. I receive this error while compiling:
kinds of the type arguments ([α]scalaz.Kleisli[[+X]X,X,α],A,B)
do not conform to the expected kinds of the type parameters (type F,type A,type B).
[α]scalaz.Kleisli[[+X]X,X,α]'s type parameters do not match type F's expected parameters:
type α is invariant, but type _ is declared covariant
[ERROR] def eitherReaderM[X,A,B](f: X => /[A,B]): EitherReaderM[X,A,B] = EitherT({type λ[α] = Reader[X, α]})#λ, A,B
And here we have it, the final, compiling version. I feel like it can be simplified a little more, but that is for a different day.
type EitherReader[X,A,B] = EitherT[({type λ[+α] = Reader[X, α]})#λ, A,B]
def eitherReader[X,A,B](f: X => \/[A,B]): EitherReader[X,A,B] = EitherT[({type λ[+α] = Reader[X, α]})#λ, A,B](Reader(f))
The allows me to replace Reader[X, A / B].apply with eitherReader[X,A,B].
Old:
def getSub(id: Int) = Reader[Config, String \/ Sub](config => config.findSub(id).right)
New:
def getSub(id: Int) = eitherReader[Config, String, Sub]](config => config.findSub(id).right)
Seems weird that I'm doing this simply for type conversion. Probably means I'm overlooking something.
Related
This question already has answers here:
How can I define an anonymous generic Scala function?
(2 answers)
Closed 9 years ago.
As most of you probably know you can define functions in 2 ways in scala, there's the 'def' method and the lambda method...
making the 'def' kind generic is fairly straight forward
def someFunc[T](a: T) { // insert body here
what I'm having trouble with here is how to make the following generic:
val someFunc = (a: Int) => // insert body here
of course right now a is an integer, but what would I need to do to make it generic?
val someFunc[T] = (a: T) => doesn't work, neither does val someFunc = [T](a: T) =>
Is it even possible to make them generic, or should I just stick to the 'def' variant?
As Randall Schulz said, def does not create a function, but a method. However, it can return a function and this way you can create generic functions like the identity function in Predef. This would look like this:
def myId[A] = (a: A) => a
List(1,2,3) map myId
// List(1,2,3)
List("foo") map myId
// List("foo")
But be aware, that calling myId without any type information infers Nothing. In the above case it works, because the type inference uses the signature of map, which is map[B](f: A => B) , where A is the type of the list and B gets infered to the same as A, because that is the signature of myId.
I don't believe it's possible. You can look at this previous post for more details:
How can I define an anonymous generic Scala function?
The only way around it (as one of the answers mentions) is to extend something like FunctionX and use a generic at the class level and then use that in the override of the apply function.
I don't believe it's possible either, but I'm a pessimist.
http://www.chuusai.com/2012/04/27/shapeless-polymorphic-function-values-1/
Edit:
Tell me if this isn't what you're asking, but this is why the accepted answer isn't what I thought you were asking for, see the link:
scala> :pa
// Entering paste mode (ctrl-D to finish)
def myId[A] = (a: A) => a
List(1,2,3) map myId
// List(1,2,3)
List("foo") map myId
// List("foo")
// Exiting paste mode, now interpreting.
myId: [A]=> A => A
res0: List[String] = List(foo)
scala> val f1 = myId[Int]
f1: Int => Int = <function1>
scala> val f2 = myId[String]
f2: String => String = <function1>
scala> List(1,2,3) map f2
<console>:10: error: type mismatch;
found : String => String
required: Int => ?
List(1,2,3) map f2
^
scala> List("foo") map f1
<console>:10: error: type mismatch;
found : Int => Int
required: String => ?
List("foo") map f1
^
The function values are not polymorphic, i.e., generic.
The closest thing is polymorphic functions I believe:
https://github.com/milessabin/shapeless#polymorphic-function-values
I am trying to figure out the issue, and tried different styles that I have read on Scala, but none of them work. My code is:
....
val str = "(and x y)";
def stringParse ( exp: String, pos: Int, expreshHolder: ArrayBuffer[String], follow: Int )
var b = pos; //position of where in the expression String I am currently in
val temp = expreshHolder; //holder of expressions without parens
var arrayCounter = follow; //just counts to make sure an empty spot in the array is there to put in the strings
if(exp(b) == '(') {
b = b + 1;
while(exp(b) == ' '){b = b + 1} //point of this is to just skip any spaces between paren and start of expression type
if(exp(b) == 'a') {
temp(arrayCounter) = exp(b).toString;
b = b+1;
temp(arrayCounter)+exp(b).toString; b = b+1;
temp(arrayCounter) + exp(b).toString; arrayCounter+=1}
temp;
}
}
val hold: ArrayBuffer[String] = stringParse(str, 0, new ArrayBuffer[String], 0);
for(test <- hold) println(test);
My error is:
Driver.scala:35: error: type mismatch;
found : Unit
required: scala.collection.mutable.ArrayBuffer[String]
ho = stringParse(str, 0, ho, 0);
^one error found
When I add an equals sign after the arguments in the method declaration, like so:
def stringParse ( exp: String, pos: Int, expreshHolder: ArrayBuffer[String], follow: Int ) ={....}
It changes it to "Any". I am confused on how this works. Any ideas? Much appreciated.
Here's a more general answer on how one may approach such problems:
It happens sometimes that you write a function and in your head assume it returns type X, but somewhere down the road the compiler disagrees. This almost always happens when the function has just been written, so while the compiler doesn't give you the actual source (it points to the line where your function is called instead) you normally know that your function's return type is the problem.
If you do not see the type problem straight away, there is the simple trick to explicitly type your function. For example, if you thought your function should have returned Int, but somehow the compiler says it found a Unit, it helps to add : Int to your function. This way, you help the compiler to help you, as it will spot the exact place, where a path in your function returns a non-Int value, which is the actual problem you were looking for in the first place.
You have to add the equals sign if you want to return a value. Now, the reason that your function's return value is Any is that you have 2 control paths, each returning a value of a different type - 1 is when the if's condition is met (and the return value will be temp) and the other is when if's condition isn't (and the return value will be b=b+1, or b after it's incremented).
class Test(condition: Boolean) {
def mixed = condition match {
case true => "Hi"
case false => 100
}
def same = condition match {
case true => List(1,2,3)
case false => List(4,5,6)
}
case class Foo(x: Int)
case class Bar(x: Int)
def parent = condition match {
case true => Foo(1)
case false => Bar(1)
}
}
val test = new Test(true)
test.mixed // type: Any
test.same // type List[Int]
test.parent // type is Product, the case class super type
The compiler will do its best to apply the most specific type it can based on the possible set of result types returned from the conditional (match, if/else, fold, etc.).
I would like to implement a type-parametrized function as per excersize on page 72 of the book (implement forall using filter):
def forallA[B <: A](xs:List[A])(f:A => B) : List[B] = {
xs.filter(x => true) match {
case Nil => Nil
case y :: ys => f(y) :: forallA(ys)(f)
}
}
However, the compiler(2.9.1) complains about the type A being undefined. Clearly that should not be the case, since multiple examples in the same book use this syntax. The issue can be cured by changnig the function type parameter to [A, B <: A]. Am I doing something wrong, or is it again, a terrific change in Scala's syntax specification? If so, I am, frankfully, tired of bombing SO with such stupid questions on every second excersize. Could anyone recommend a book that clearly reflects the current order of things?
You already gave the answer: If you want to bound the type parameter B with another type parameter A, you have to add this to the list of type parameters:
def forall[A, B <: A](...)(...) = ...
Else you are referring to something undefined. Maybe it helps if you think of type parameters like usual (method) parameters. How should something like the following compile:
def add(x: Int) = x + y
Here the parameter y is undefined, just like in your case A was undefined.
I'm implementing an actor-based app in scala and I'm trying to be able to pass functions between the actors for them to be processed only when some message is received by the actor.
import actors.Actor
import java.util.Random
import scala.Numeric._
import Implicits._
class Constant(val n:Number) extends Actor{
def act(){
loop{
receive{
case "value" => reply( {n} )
}
}
}
}
class Arithmetic[T: Numeric](A: ()=>T, B: ()=>T) extends Actor{
def act(){
receive{
case "sum" => reply ( A() + B() )
/* case "mul" => reply ( A * B )
*/
}
}
}
object Main extends App{
val c5 = new Constant(5)
c5.start
val a = new Arithmetic({c5 !! "value"}, {c5!!"value"} )
a.start
println(a!?"sum")
println(a!?"mul")
}
In the example code above I would expect the output to be both 5+5 and 5*5. The issue is that reply is not a typed function and as such I'm unable to have the operator (+,*) to operate over the result from A and B.
Can you provide any help on how to better design/implement such system?
Edit: Code updated to better reflect the problem. Error in:
error: could not find implicit value for evidence parameter of type Numeric[Any]
val a = new Arithmetic({c5 !! "value"}, {c5!!"value"} )
I need to be able to pass the function to be evaluated in the actor whenever I call it. This example uses static values but I'll bu using dynamic values in the future, so, passing the value won't solve the problem. Also, I would like to receive different var types (Int/Long/Double) and still be able to use the same code.
The error: Error in: error: could not find implicit value for evidence parameter of type Numeric[Any]. The definition of !!:
def !! (msg: Any): Future[Any]
So the T that Arithmetic is getting is Any. There truly isn't a Numeric[Any].
I'm pretty sure that is not your problem. First, A and B are functions, and functions don't have + or *. If you called A() and B(), then you might stand a chance... except for the fact that they are java.lang.Number, which also does not have + or * (or any other method you'd expect it to have).
Basically, there's no "Number" type that is a superclass or interface of all numbers for the simple reason that Java doesn't have it. There's a lot of questions touching this subject on Stack Overflow, including some of my own very first questions about Scala -- investigate scala.math.Numeric, which is the best approximation for the moment.
Method vs Function and lack of parenthesis
Methods and functions are different things -- see tons of related questions here, and the rule regarding dropping parenthesis is different as well. I'll let REPL speak for me:
scala> def f: () => Int = () => 5
f: () => Int
scala> def g(): Int = 5
g: ()Int
scala> f
res2: () => Int = <function0>
scala> f()
res3: Int = 5
scala> g
res4: Int = 5
scala> g()
res5: Int = 5
I'm new to Scala, and being able to pass functions to other functions is pretty neat-- but can I pass an arbitrary function reference to another function? The arity of said functional parameter will be fixed (that said, I'm also curious about whether you can pass a function with arbitrary arity as well). I keep getting tripped up on type errors. I've tried using Any but it doesn't seem to help.
E.g., I have the code below:
class CodeRunner(val user_defined: (Int) => Unit) {
def run(input: Int) = {
user_defined(input)
}
}
def arbitrary_code(input: Int) = { println("Running with input " + input) }
val d1 = new CodeRunner(arbitrary_code)
d1.run(4)
And I get:
Running with input 4
Now, let's say that I want to pass the following function instead:
def arbitrary_code(input: String) = { println("Running with input " + input) }
How can I change my CodeRunner class to handle both?
How can I change my CodeRunner class to handle both?
You can make the arbitrary type a parameter of the class:
class CodeRunner[T](val user_defined: (T) => Unit) {
def run(input: T) = {
user_defined(input)
}
}
def arbitrary_code(input: Int) = { println("Running with input " + input) }
val d1 = new CodeRunner(arbitrary_code)
d1.run(4)
def arbitrary_code2(input: String) = { println("Running with input " + input) }
val d2 = new CodeRunner(arbitrary_code2)
d2.run("hello")
Note that the type of d2 is CodeRunner[String] which is not assignable to d1 which is CodeRunner[Int].
Generic types allow you to define a class with a placeholder type that gets specified when an object gets instantiated. The compiler is happy because it can make sure that everything is type safe, and you're happy because you can instantiate the object and pass in arbitrary types for the value.
To use a generic type with your class, you could modify it like this:
class CodeRunner[T] (val user_defined: (T) => Unit) {
def run(input: T) = {
user_defined(input)
}
}
The [T] after "class CodeRunner" is the important part -- it defines that there is a generic type T (you could replace T with another capital letter, etc.) which will be used within the class definition.
So, if you define a method:
def arbitrary_code(input: String) = { println("Running with input " + input) }
and then pass it in:
val d1 = new CodeRunner(arbitrary_code)
... the compiler then says "aha, for this instance of CodeRunner the generic type T is a string". And if you invoke
d1.run("string")
the compiler will be happy, but won't let you pass in d1.run(4).
To pass an arbitrary function you can certainly use generics :
def run[T,U](f: T => U) = println(f)
For arbitrary arity, it's impossible because a function of type T => U is instance of Function1[U,T] and a function of type (T,U) => V is an instance of Function2[T,U,V]. (Also, I couldn't find any useful use case).
However, there is a smart concept called "currying". It consists in transforming a function that takes multiple arguments and return a value in a function that takes a single argument and returns another function.
Here's an example :
def nonCurriedAdd(x: Int, y: Int) = x + y
// nonCurriedAdd(4,6)
def curriedAdd(x: Int) = (y: Int) => x + y
// we can use some syntax sugar
def curriedAdd(x: Int)(y: Int) = x + y
// curriedAdd(4)(6)
So, you can now do `d1.run(curriedAdd).
You can also transform a non-curried function in a curried one by using the "curried" method :
d1.run(nonCurriedAdd.curried)
can I pass an arbitrary function reference to another function? The arity of said functional parameter will be fixed
As always, write down the type of the function you are developing, and all becomes clear.
Your word "arbitrary" suggests that the function arguments work at any type. That is, they are polymorphic functions (or generic functions, in some languages).
The following should translate fairly cleanly to Scala:
== The type of an "arbitrary" function of fixed arity
f :: a -> b -> c -> d
-- The type of a function that accepts such a
-- function as an argument, and does something with it:
g :: (a -> b -> c -> d) -> a -> b -> c -> d
-- And a function that implements something of that type
g f a b c = f a b c
You might be able to come up with a few other such higher-order functions, that take functions of fixed arity, but arbitrary (i.e. polymorphic) type, and operate on them.
Classic higher-order functions are e.g.
map :: (a -> b) -> [a] -> [b]
fold :: (a -> b -> b) -> b -> [a] -> b
And many, many others.
scala> object codeRunner {
| def run[InputType, OutputType](code: InputType => OutputType) = (input: InputType) => code(input)
| }
defined module codeRunner
scala> def someCode(x: Int) {
| println("This code uses " + x)
| }
someCode: (x: Int)Unit
scala> def otherCode(y: String) {
| println("This code uses " + y)
| }
otherCode: (y: String)Unit
scala> codeRunner.run(someCode)(10)
This code uses 10
scala> codeRunner.run(otherCode)("hello")
This code uses "hello"