list - 在列表 monad 中使用 return 与不使用 return

标签 list haskell monads do-notation

我开始了我的 Grand Haskell Crusade (GHC:)),我对 monad 和 IO 函数有点困惑。谁能简单解释一下这两个函数有什么区别?

f1 = do x <- [1,2]
        [x, x+1] -- this is monad, right?

f2 = do x <- [1,2]
        return [x, x+1]

结果是:

*Main> f1
[1,2,2,3]

*Main> f2
[[1,2],[2,3]]

最佳答案

要了解为什么会得到特定的答案,脱糖解释非常有帮助。让我用一些关于培养 Haskell 代码认知的一般性建议来补充它们。

Haskell 的类型系统不区分两个可分离的“道德”目的:

  • [x] 的类型,它是包含从 x 中提取的元素的列表
  • [x] x 元素的计算类型,允许优先选择

这两个概念具有相同的表示形式并不意味着它们发挥相同的作用。在f1中,[x, x+1]扮演着计算的角色,因此它生成的可能性被合并到整个计算生成的选择中:这就是列表 monad 的 >>= 会执行此操作。然而,在 f2 中,[x, x+1] 扮演的是值的角色,因此整个计算会在两个值之间生成优先级选择(这恰好是是列表值)。

Haskell 不使用类型来进行这种区分[你现在可能已经猜到我认为应该这样做,但那是另一个故事了]。相反,它使用语法。所以你需要训练你的大脑在阅读代码时感知值(value)和计算角色。 do 表示法是用于构造计算的特殊语法。 do 中的内容是根据以下模板套件构建的:

jigsaw pieces for computations

三个蓝色部分进行do计算。我将计算孔标记为蓝色,将值孔标记为红色。这并不意味着是一个完整的语法,只是一个如何在你的头脑中感知代码片段的指南。

事实上,您可以在蓝色位置编写任何旧表达式,前提是它具有适当的单子(monad)类型,并且如此生成的计算将根据需要使用 >>= 合并到整体计算中。在您的 f1 示例中,您的列表位于蓝色位置,并被视为优先选择。

类似地,您可以在红色位置编写表达式,这些表达式很可能具有一元类型(如本例中的列表),但它们仍然会被视为值。这就是 f2 中发生的情况:结果的外括号是蓝色的,但内括号是红色的。

训练你的大脑在阅读代码时将值/计算分开,这样你就能本能地知道文本的哪些部分在做什么工作。一旦你重新编程了你的大脑,f1f2 之间的区别看起来就完全正常了!

关于list - 在列表 monad 中使用 return 与不使用 return,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11323300/

相关文章:

java - 删除列表中的重复项

c# - 使用 Linq 检查元组列表是否包含一个元组,其中 Item1 = x

haskell - 对 Haskell 的布局工具如何处理此代码感到困惑

haskell - 在不考虑实现细节的情况下定义与其他函数相关的函数

list - Haskell:用一个元素和一个列表连接元组列表:[(a,[b])] -> [(a,b)]

python - 如何在python中按天排序基于键的字典

Python 使用另一个列表中的信息生成列表时出现问题

haskell - 编写可选的 Aeson 解析器

haskell - 如何在没有 Do 符号的情况下写作

scala Iterable#map 与 Iterable#flatMap