Haskell。为什么它有效? (迭代 Monad)

Haskell. Why it is working? (Iteration over Monad)

liftMM :: Monad m => (a -> b) -> m a -> m b
liftMM f m = m >>= \a -> return (f a)

我运行:

> liftMM (*2) [1..10]

我得到了输出:

> [2,4,6,8,10,12,14,16,18,20]

我看不出这个函数是如何映射所有列表的值的?没有任何递归或迭代,只是将 monad 内部 m 值传递给函数 f。我在这里缺少什么?

列表是 monad,因此给定地图的签名:

map :: (a->b) -> [a] -> [b]

和 liftMM 的签名

liftMM :: Monad m => (a -> b) -> m a -> m b

[]m

这意味着 for lists liftMMmap 做同样的事情。

m 这里是 []liftMM 通过委派 (>>=)return 的实现来实现 m。因此,您需要了解列表的 (>>=)return,如果您查看 definition,它们是:

instance Monad []  where
    xs >>= f            = [y | x <- xs, y <- f x]
    return x            = [x]

因此对于源列表中的每个元素 >>= 应用 f 然后将返回列表的每个元素插入到结果列表中。

return x 只是 returns 一个包含 x 的单例列表,所以 return (f a) returns 一个列表 [f a]。然后 (>>=) 组合这些单个元素列表中的每一个以创建输出列表。