【问题标题】:Haskell Monadic Operations on Lists列表上的 Haskell Monadic 操作
【发布时间】:2012-05-06 21:12:52
【问题描述】:

我有以下

[3,2,1] >> [1]
= [1,1,1]

我不完全明白为什么会发生这种情况?看着 >> 我希望 [3,2,1] 是结果,但我发现这在列表中有所不同。

谁能解释一下原因?

【问题讨论】:

  • 想想会发生什么,IO monad 确实以类似的方式表现...putStr "Hello," >> putStr " world" 将是一个打印 " world" 的操作。
  • 如果您解释了为什么您期望得到您建议的结果,这可能会有所帮助。
  • @leftaroundabout:想想(>>) :: Monad m => m a -> m b -> m b 的类型。就IO 而言,这将是“分别组合IO aIO b 类型的两个动作,并产生IO b 类型的动作”。想想(getLine >> getLine) :: IO String:它从标准输入中读取两行,丢弃读取第一行的结果,返回读取第二行的结果。 ([3,2,1] >> ["Hello", "World"]) :: [String] 类似:选择一个数字,然后选择一个字符串,然后返回字符串,隐式丢弃该数字。
  • @sacundim:我的观点与丢弃的“返回”单子参数数据无关(这就是我选择输出动作的原因,因为那些只有()),它是关于结构.
  • @leftaroundabout:我想我在得到你的回复之前就明白了你的意思。我刚刚提交了您可能感兴趣的this question

标签: list haskell monads


【解决方案1】:

对于任何 monad,您可以将 a >> b 翻译为 a >>= \_ -> b。在列表 monad 中,绑定运算符 (>>=)concatMap,其参数翻转,因此您的示例等效于

concatMap (\_ -> [1]) [3, 2, 1]

你可以这样评估。

concatMap (\_ -> [1]) [3, 2, 1]
= concat (map (\_ -> [1]) [3, 2, 1])   -- definition of concatMap
= concat [[1], [1], [1]]               -- apply map
= [1, 1, 1]                            -- apply concat

【讨论】:

    【解决方案2】:

    >> 可以这样定义:

    ma >> mb = ma >>= const mb
    

    (这不是它在 Monad 实例中对 [] 的实际定义,但这没关系。)

    在列表的情况下,对于[1,2,3]中的每个元素,你得到[1],整体结果等价于concat [[1],[1],[1]],即[1,1,1]

    这是 GHC.Base 中[] 的实例:

    m >>= k             = foldr ((++) . k) [] m
    m >> k              = foldr ((++) . (\ _ -> k)) [] m
    

    我们在这里使用折叠连接左侧每个元素的右侧副本,忽略该元素可能是什么。

    【讨论】:

    • 我不明白“const mb”这个东西。 const a -> b -> a 所以我希望 mb 被输出。即 [1]
    • 是的,没错,输出的是mb。它输出三次,因为在列表的情况下,对于左侧列表的每个元素,>>>>= 的右侧被调用一次。所以你得到[[1],[1],[1]]
    【解决方案3】:

    回想一下,列表的return\x -> [x]。如果我用return 重写你的例子,也许会更清楚

    [1,2,3] >> return 1
    

    让我们添加一些符号糖

    do [1,2,3]
       return 1
    

    你现在能看到吗? >> 不会从其左侧参数中提取值,仅从它们周围的 context 中提取值。在这种情况下,上下文是一个 3 元素列表,或者您可能会说,3 个不同的选择都是非确定性选择的。然后在每种情况下,return 1

    如果你这样做了

    do x <- [1,2,3]
       return x
    

    那么您不是在每种情况下都选择 1,而是x,它代表每个“分支”的特定选择。尝试猜测这将是什么结果,然后检查 ghci 看你是否正确。然后对其进行脱糖,并使用等式推理得到正确答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-27
      相关资源
      最近更新 更多