Reputation: 1935
Given a higher Kinded Type M, and a monad type class, I can operate on values within M through a for-comprehension. Working with a function that return Options, im looking for a more appropriate way to flatten these options than the solution I have. This is as follows
class Test[M[+_]:Monad](calc:Calculator[M]) {
import Monad._
def doSomething(x:Float):M[Option[Float]] = {
for {
y:Option[Float] <- calc.divideBy(x) // divideBy returns M[Option[Float]]
z:Option[Float] <- y.fold[M[Option[Float]]](implicitly[Monad[M]].point(None))(i => calc.divideBy(i))
} yield z
}
}
So its the following I'm looking to correct:
y.fold[M[Option[Float]]](implicitly[Monad[M]].point(None))(i => calc.divideBy(i))
Also the case where instead of calling the second divideBy, I call multiplyBy which returns M[Float]
y.fold[M[Option[Float]]](implicitly[Monad[M]].point(None))(i => calc.multipleBy(i).map(Some(_))
Maybe this is a case for Monad Transformers but Im not sure how to go about it.
Upvotes: 2
Views: 121
Reputation: 139038
It seems likely that monad transformers can help you here. For example, the following compiles and I think does roughly what you want:
import scalaz._, Scalaz._
abstract class Calculator[M[_]: Monad] {
def divideBy(x: Float): M[Option[Float]]
def multiplyBy(x: Float): M[Float]
}
class Test[M[_]: Monad](calc: Calculator[M]) {
def doSomething(x: Float): OptionT[M, Float] = for {
y <- OptionT(calc.divideBy(x))
z <- calc.multiplyBy(y).liftM[OptionT]
} yield z
}
Now doSomething
returns an OptionT[M, Float]
, which is kind of wrapper for M[Option[Float]]
that allows you to work with the contents all the way inside the Option
monadically. To get back an M[Option[Float]]
from the OptionT[M, Float]
you can just use the run
method.
Upvotes: 2