gpt4 book ai didi

scala - 比较 Haskell 和 Scala 绑定(bind)/平面图示例

转载 作者:行者123 更新时间:2023-12-03 14:39:19 27 4
gpt4 key购买 nike

以下bind(>>=) 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 的 >>=签名是:
>>= :: 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]

只有一个问题, Option不是 GenTraversableOnce 的子类, 这里有一个隐式转换。Scala 定义了一个来自 Option 的隐式转换至 Iterable它是 Traversable 的子类它是 GenTraversableOnce 的子类.
implicit def option2Iterable[A](xo: Option[A]): Iterable[A]   

隐式定义在 Option 的伴随对象中。 .

查看隐含作用的更简单方法是分配 OptionIterable val :
scala> val i:Iterable[Int] = Some(1)
i: Iterable[Int] = List(1)

Scala 使用一些默认规则来选择 List作为 Iterable 的实现.

您可以组合 TraversableOnce 的不同子类型这一事实带有 monad 的操作来自 implicit class 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 就是这种情况。 .

关于scala - 比较 Haskell 和 Scala 绑定(bind)/平面图示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29187983/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com