Reputation: 1045
Lets say we have a function
f: (A, A) => A
and we are given two optional values
val x: Option[A] = ...
val y: Option[A] = ...
Now we want to apply the function f
to x
,y
. In case one of the parameters is None
, we want to return None
. In scalaz we could write
^(x, y)(f)
Now assume that we want to restrict the input parameters for function f
by coming up with another function which checks if the parameters meet a constraint. If so the function applies f
to its arguments and returns the result wrapped in a Some
object. Otherwise it returns None
:
fRestricted: (A, A) => Option[A]
The problem now is that we cannot make use of Scalaz anymore, i.e.
^(x, y)(fRestricted)
does not work anymore, since the types are wrong.
Is this actually a common problem? Is there a generic solution for the use case?
Upvotes: 2
Views: 95
Reputation: 43310
It is one of the most basic problems in functional programming (not just Scala).
The thing you were doing with Scalaz was based on applicative functor capabilities of the Option
. Unfortunately the standard Scala library does not support applicative functors, however it does support monads, and Option
is also a monad. Applicative functors are strictly a more general thing than monads, so whatever applicative functors can do, monads can do too.
Here's how you can exploit the fact that Option
is a monad to solve your problem with the standard library:
for {
a <- x
b <- y
c <- fRestricted(a, b)
}
yield c
The syntax above is called a "for-comprehension", and in fact it is nothing more than just a sugar for the following:
x.flatMap( a => y.flatMap( b => fRestricted(a, b) ) )
Upvotes: 2