每当我阅读有关Monad的示例时,他们总是将IO作为案例研究。

是否有任何例子说明有人可能会执行单子(monad)操作列表?我认为这可能会过大,但是我很想知道monads是否能比常规列表操作技术具有优势。

最佳答案

Haskell中列表monad的最大 secret 在于,列表理解是do块的语法糖。每当您编写列表推导时,您都可以使用do块来编写它,该代码使用list monad实例。

一个简单的例子

假设您要获取两个列表,并返回其笛卡尔积(即,第一个列表中的(x,y)和第二个列表中的x的每种组合的y列表)。

您可以通过列表理解来做到这一点:

ghci> [(x,y) | x <- [1,2], y <- [3,4]] -- [(1,3),(1,4),(2,3),(2,4)]

列表理解是此do块的语法糖:
zs = do x <- [1,2]
        y <- [3,4]
        return (x,y)

反过来又是语法糖
zs = [1,2] >>= \x -> [3,4] >>= \y -> return (x,y)

一个更复杂的例子

但是,该示例并未真正展示monad的功能,因为您可以轻松编写它,而无需依赖列表包含Monad实例的事实。例如,如果我们仅使用Applicative实例:
ghci> import Control.Applicative
ghci> (,) <$> [1,2] <*> [3,4] -- [(1,3),(1,4),(2,3),(2,4)]

现在假设您将一个正整数列表中的每个元素都复制了很多次(例如f [1,2,3] = [1,2,2,3,3,3])。谁知道您为什么要这样做,但这很容易:
ghci> let f xs = [ y | x <- xs, y <- replicate x x ]
ghci> f [1,2,3] -- [1,2,2,3,3,3]

这只是语法糖:
f xs = do x <- xs
          y <- replicate x x
          return y

这反过来又是语法糖
f xs = xs >>= \x -> replicate x x >>= \y -> return y

这次我们不能仅使用应用实例来编写它。关键区别在于我们从第一个绑定(bind)(x)中获取了输出,并使其余的块依赖于它(y <- replicate x x)。

关于haskell - 使用monad来完成诸如列表操作之类的琐碎任务?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12706640/

10-11 22:35
查看更多