比较Haskell和Scala绑定/平面图示例
Haskell中的以下绑定(>> =)代码不会编译:
ghci> [[1]] >>= Just <interactive>:38:11: Couldn't match type ‘Maybe’ with ‘[]’ Expected type: [t] -> [[t]] Actual type: [t] -> Maybe [t] In the second argument of ‘(>>=)’,namely ‘Just’ In the expression: [[1]] >>= Just 但是,在Scala中,它确实编译并运行: scala> List( List(1) ).flatMap(x => Some(x) ) res1: List[List[Int]] = List(List(1)) Haskell’s>> =签名是: >> = :: Monad m => m a – > (a→m b)→> m b 所以,在[[1]]>> = f中,f的类型应该是:a – >并[b]. 为什么Scala代码编译? 解决方法
正如@chi所说,Scala的flatMap比Haskell的>> =更为通用. Scala文档的完整签名是:
final def flatMap[B,That](f: (A) ? GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A],B,That]): That 这个隐含的与这个具体问题无关,所以我们可以使用更简单的定义: final def flatMap[B](f: (A) ? GenTraversableOnce[B]): List[B] 只有一个问题,选项不是GenTraversableOnce的子类,这里是一个隐式转换.Scala定义了从Option到Iterable的隐式转换,它是Traversable的子类,它是GenTraversableOnce的子类. implicit def option2Iterable[A](xo: Option[A]): Iterable[A] 隐含在Option的伴随对象中定义. 在工作中看到隐式的一个更简单的方法是将一个选项分配给一个Iterable val: scala> val i:Iterable[Int] = Some(1) i: Iterable[Int] = List(1) Scala使用一些默认规则,选择List作为Iterable的实现. 事实上,你可以组合TraversableOnce的不同子类与monad操作来自隐式类MonadOps: implicit class MonadOps[+A](trav: TraversableOnce[A]) { def map[B](f: A => B): TraversableOnce[B] = trav.toIterator map f def flatMap[B](f: A => GenTraversableOnce[B]): TraversableOnce[B] = trav.toIterator flatMap f def withFilter(p: A => Boolean) = trav.toIterator filter p def filter(p: A => Boolean): TraversableOnce[A] = withFilter(p) } 这可以通过上述方法增强每个TraversableOnce的功能.子类型可以自由定义更有效的版本,这些将隐含隐含的定义.这是List的情况. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |