List Monad:List.flatMap签名的后果(f:(A)⇒GenTraversableOnce[B])

时间:2014-05-29 22:08:39

标签: list scala functional-programming option monads

最近我偶然发现了一些不应该有效的代码。这是一个简化的插图:

val l=List(1,2,3,4,5)
def isEven(i:Int):Option[Int] = if (i%2==0) Some(i) else None

for {elem <- l
     even <- isEven(elem)
    } yield even

这将产生List(2,4),对Scala开发人员来说可能并不奇怪。

但鉴于List是monadic并且应该是这种形式,它不应该工作:

class M[A] {
    def flatMap[B](f:A => M[B]):M[B]
    def map[B](f:A => B):M[B]
}

遵循此定义,monadic操作链中的每个元素都必须属于同一个monad。地图在monad的上下文中转换元素,并且flatMap必须陷阱&#39;免费元素进入monad。 在上面的例子中,我们有这个desugarized表示:

l.flatMap(elem => isEven(elem))

类型为:List[Int].flatMap[Int](f:Int => Option[Int])且不符合monadic定义。

isEven的正确形式应该是:

def isEven(i:Int):List[Int] = if (i%2==0) List(i) else Nil

查看scala-docs,结果表明ListOption可以在Scala中进行理解的原因是flatMap {{1}定义为List并允许任何可遍历的实例进行平面映射&#39;过度。 flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): List[B]可以移动,OptionSet,其他许多也是可以访问的。

我想知道:Seq这个更广泛定义的后果是什么。

是否有人应该注意/小心?

1 个答案:

答案 0 :(得分:2)

您列出的签名是臭名昭着的“用例”,而不是方法签名,即“完整签名”。

def flatMap[B, That](f: (A) ⇒ GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That

您可以构建任何有CanBuildFrom

的目标

问题相当广泛;我不确定已列出的后果清单。

Is the Scala 2.8 collections library a case of "the longest suicide note in history"?

The attempt to do so in the space of one talk.

或者例如:

https://stackoverflow.com/a/17377859/1296806