每当我阅读有关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/