Monad变压器用于理解

时间:2011-10-30 08:40:52

标签: scala monad-transformers for-comprehension

考虑:

def xs(c: String): Option[List[Long]] = ...

val ys: Stream[Long] = ...

现在我写一个类似的方法:

def method(oc: Option[String]): Option[Long] = for { 
    c <- oc
    list <- xs(c)
} yield{        
    for {
        first <- ys.find(list contains _)
    } yield first
}

但当然这不会编译,因为推断类型是Option [Option [Long]]。

scala语法和标准库是否有办法获得Option [Long]?我知道我可以模式匹配,但问题是否只能用于理解才能完成。


感谢tenshi的答案,这就完成了工作,但是我刚遇到了另一个问题的例子:

class T
class U
class A(t: String)(implicit x: T)
def getU(a: A): Option[U] = ...

def getU_2(oc: Option[String]): Option[U] = for{
   c <- oc
} yield{
   implicit val someImplicit: T = new T
   val a = A(c)

   getU(a)
}

我可以在for中添加aa <- Some(A(c))但隐含的是什么?这是否意味着我的代码中的设计更改?

1 个答案:

答案 0 :(得分:7)

为什么使用2个嵌套for理解?不应该做这个工作吗?

def method(oc: Option[String]): Option[Long] = 
    for { 
        c <- oc
        list <- xs(c)
        first <- ys.find(list contains _)
    } yield first 

更新

关于你的第二个例子。你可以在别处定义隐式并导入它或在方法的开头定义它,但我想你想让它的范围尽可能地缩小。在这种情况下,您可以直接在for理解中使用块:

def getU_2(oc: Option[String]): Option[U] = for {
   c <- oc
   a <- {
       implicit val someImplicit: T = new T
       getU(new A(c))
   }
} yield a

或(可能是最简单的)明确地提供隐式参数:

def getU_2(oc: Option[String]): Option[U] = for {
   c <- oc
   a <- getU(new A(c)(new T))
} yield a