I am trying to create the following lift function but I am hitting a brick wall:
scala> def liftOff[A,B](f : A => B) : A => Option[B] = _.map(f)
<console>:10: error: value map is not a member of type parameter A
def liftOff[A,B](f : A => B) : A => Option[B] = _.map(f)
I thought I could denote that the type parameter A is mappable but the mappable trait is now deprecated since 2.10. If the input type of the returned function is an Option it's not a problem but that is not what I need:
scala> def liftOff[A,B](f : A => B) : Option[A] => Option[B] = _ map f
liftOff: [A, B](f: A => B)Option[A] => Option[B]
Is there a way to do this?
If what you are trying to define is a method that takes a function from A to B, and returns a function from A to Option[B], then you just need to combine f with a function to enclose the result in an Option, such as:
def liftOff[A,B](f : A => B) : A => Option[B] = f andThen Option.apply
if this isn't what you meant, then you might need to edit your question to make your intent clearer.
Another option is to lift* it to the Option type first:
scala> def liftOff[A,B](f : A => B) : A => Option[B] = Some(_) map f
liftOff: [A, B](f: A => B)A => Option[B]
scala> liftOff((x:Int) => 2.0 * x)(3)
res6: Option[Double] = Some(6.0)
*Note: Here Some is the unit/return method lifting A to a monadic (Option) type.
Related
I have case class State and want to extend Variable class from it; but in Variable class only need value in constructor. Where can I put run function?
case class State[S, +A](run: S => (A, S)) {
//.....has `map` function
def map[B, X >: State[S, B]](f: A => B): X =
State(state => {
val (a, s2) = run(state)
(f(a), s2)
})
}
class Variable[+A](value: A) extends State[A, A] { // ERROR
def get: Variable[A] =
map(x => x)
def set(newValue: A): Variable[A] =
map(_ => newValue)
}
UPDATE
I've changed to something like this:
class Variable[+A](value: A, run: A => (A, A)) extends State[A, A](run) {
def get: Variable[A] =
map(x => x) // ERROR HERE
def set(newValue: A): State[A, A] =
map(_ => newValue)
}
object Variable {
def create[A](value: A): Variable[A] = new Variable[A](value, x => (x, x))
}
But I've gotten error:
type mismatch; found : com.libs.State[A,A] required: com.libs.Variable[A] Variable.scala /scala/src/com/libs line 4 Scala Problem
The problem is that you cannot define a Variable using map, since map defines a State which is only a super-type of Variable. How can your program know how to set the additional information of your subclass, using only map?
However, if you define type Variable[+A] = State[A, A], so that it is not a subclass but an alias for the same class, you will have some variance errors, since State is invariant in its type parameter S, so Variable must be too.
I don't understand why this code compiles :
def lift[A,B](f: A => B): Option[A] => Option[B] = _ map f
If I do :
val f: Int => Double = _.toDouble
Then lift(f) works fine, but f map f gives an error : error: value map is not a member of Int => Double
I don't understand why this code compiles :
def lift[A,B](f: A => B): Option[A] => Option[B] = _ map f
It's short for
def lift[A,B](f: A => B): Option[A] => Option[B] = (o: Option[A]) => o map f
Method lift returns a function that:
- takes an Option[A]
- modifies that option's contents using some function f: A => B
- returns the result, Option[B]
So, when you "lift" some function f: A => B, you basically upgrade it from A => B to Option[A] => Option[B]. When this new upgraded function is given o: Option[A], it will map that option's content into Option[B] (by using f: A => B which was provided when original function was being upgraded).
If I do:
val f: Int => Double = _.toDouble
Then lift(f) works fine, but f map f gives an error error: value map is > not a member of Int => Double
Yes, because you cannot map over a function. You can only map over something by using a function (by the way, things you can map over are called functors).
What you want to do is:
Define some function f (you defined val f: Int => Double = _.toDouble)
Use lift to "upgrade" you function f from Int => Double to Option[Int] => Option[Double]
Use your new upgraded function to map over an Option[Int], thereby transforming it into an Option[Double].
So:
val f: Int => Double = _.toDouble
val upgraded = lift(f)
println(upgraded(Some(8))) // prints Some(8.0)
The lift function simply lifts your function f: A=> B to the function on some other domain, in this case it is Option[_]. So, your implementation of lift gives you a function f': Option[A] => Option[B], and because Option has the map function, you can call it on the first input parameter (this is the 'underscore').
You don't have to call f map f. What you do is lifting your f function:
val f: Int => Double = _.toDouble
val lifted = lift(f)
lifted(Some(42)) //it should be Some(42.0)
I am not sure how the following function works:
def lift[A, B](f: A => B): Option[A] => Option[B] = _ map f
I know it transforms a function which takes a value of type A and returns a value of type B into a function which takes a value of type Option[A] and returns an Option[B]. But I am stuck on what the underscore is doing and how the map works. Can someone expand the function definition?
def lift[A, B](f: A => B): Option[A] => Option[B] = _ map f
it exapnds to
def lift[A, B](f: A => B): Option[A] => Option[B] = x => x map f
(this is how underscore works in this context)
The return type is annotated to be Option[A] => Option[B]. Thanks to this compiler will know that x is of type Option[A]. We can say it explicitly, expanding it further
def lift[A, B](f: A => B): Option[A] => Option[B] = (x: Option[A]) => x map f
So, the returned function takes an Option[A] and maps it using f. Option.map takes parameter that is a function A => B so everything is correct.
Note that since I annotated the type that function takes as a parameter you can now omit the type of lift method like this
def lift[A, B](f: A => B) = (x: Option[A]) => x map f
All the snippets I wrote in this post are equivalent.
_ map f in this case returns a function that takes an Option[A] and returns an Option[B].
The _ in this case is a shortcut to build and return a function by specifying its argument position.
So here, the position of the Option[A] argument.
Whenever this returned function will be further called, it would execute:
thePassedOptionA map f
I'm learning Scala and have the following toy code:
object M {
def isSorted[X](xs: Array[X], compare: (X, X) => Boolean): Boolean =
xs.dropRight(1).zip(xs.drop(1)).forall(Function.tupled(compare))
def curry[A,B,C](f: (A, B) => C) : A => (B => C) =
(a) => (b) => f(a, b)
}
My goal is to call it like:
M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
But I receive the error:
scala> M.curry(M.isSorted)(Array(1,2,3))
<console>:8: error: type mismatch;
found : Int(1)
required: Nothing
M.curry(M.isSorted)(Array(1,2,3))
Let's back up and look at the type of the curried function:
scala> M.curry(M.isSorted)
res2: Array[Nothing] => (((Nothing, Nothing) => Boolean) => Boolean) = <function1>
That's no good. It wants an Array[Nothing] but there can be no instances of Nothing.
I understand at some point I will need to introduce a constraint so the compiler can prove that the expression a < b is allowable; that is, that a and b are Ordered. But I don't know where I would put the constraint. curry is perfectly generic; the constraint doesn't belong there. isSorted knows nothing about the implementation of compare, so it doesn't belong there either.
The closest I've gotten to having it working is with def isSorted[X >: Any]
scala> M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
<console>:8: error: value < is not a member of Any
M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
^
scala> M.curry(M.isSorted)(Array(1,2,3))((a: Int, b: Int) => a < b)
<console>:8: error: type mismatch;
found : (Int, Int) => Boolean
required: (Any, Any) => Boolean
M.curry(M.isSorted)(Array(1,2,3))((a: Int, b: Int) => a < b)
^
How can I get this working?
object M {
def isSorted[X](xs: Array[X], compare: (X, X) => Boolean): Boolean =
xs.dropRight(1).zip(xs.drop(1)).forall(Function.tupled(compare))
def curry[A,B,C](f: (A, B) => C) : A => (B => C) =
(a) => (b) => f(a, b)
}
Well... I don't think this is the best way to define these functions but in this case, since these are generic functions so you need to provide them with a type when calling.
As #dk14 has pointed out in his comment... M.sorted can not get type info because Scala lacks support for polymorphic lambdas.... which simply means no generics in anonymous functions.
So you need to do this for this particular case.
M.curry( M.isSorted[Int] )( Array(1,2,3) ) ( (a , b) => a < b )
Given a val that consists of the following (what I believe is a) type constructor with a curried function argument, F[A => B => C]...
val x: F[A => B => C] = foo() // foo does not matter
Is it possible for me to get F[C] from x?
val y: F[C] = x...
EDIT
For context, I'm trying to implement the map3 function from Functional Programming in Scala.
The only way to get F[C] from F[A => B => C] is if you can apply an A and a B to it. That is, you'll need to evaluate the contained function. Use the apply twice, once to get an B => C and then once again to get C.
def eval(myApp: F[A => B => C])(value: F[A]): F[B => C]
def evalAgain(myApp: F[B => C])(value: F[B]): F[C]
but if you just want to be able to get F[C] directly from the function itself without evaluation, you're SOL.
Edit:
I believe it would look like this.
def eval(myApp: F[A => B => C])(value: F[A], next: F[B])(implicit ap: Applicative[F[_]]) = ap(ap(myApp, value), next)