2015-06-20 71 views
2

给定一个更高的Kinded类型M和monad类型的类,我可以通过for-understanding理解M内的值。使用返回Options的函数,即时寻找一种更合适的方式来扁平化这些选项,而不是我的解决方案。这是如下斯卡拉展开围绕更高kinded类型的一个选项,寻找一个更习惯的方法

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 
    } 
} 

所以其我期待更正如下:

y.fold[M[Option[Float]]](implicitly[Monad[M]].point(None))(i => calc.divideBy(i)) 

同样的情况下,而不是拨打第二分除法器,我称之为multiplyBy返回M [浮点]

y.fold[M[Option[Float]]](implicitly[Monad[M]].point(None))(i => calc.multipleBy(i).map(Some(_)) 

也许这是一个Monad变形金刚的情况,但我不知道如何去做。

回答

2

似乎monad变压器可以帮助你。例如,下面的编译,我觉得确实大概你想要什么:

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 
} 

现在doSomething返回OptionT[M, Float],这是M[Option[Float]]一种包装的,可以让你与内容一路工作Option monadically内。要从OptionT[M, Float]获取M[Option[Float]],您只需使用run方法。

相关问题