最近我偶然发现了一些不应该有效的代码。这是一个简化的插图:
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,结果表明List
和Option
可以在Scala中进行理解的原因是flatMap
{{1}定义为List
并允许任何可遍历的实例进行平面映射&#39;过度。 flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): List[B]
可以移动,Option
,Set
,其他许多也是可以访问的。
我想知道:Seq
这个更广泛定义的后果是什么。
是否有人应该注意/小心?
答案 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.
或者例如: