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。我在这里缺少什么?
m
这里是[]
并且liftMM
通过委派(>>=)
和return
for的实现来工作m
。因此,您需要了解(>>=)
和return
对于列表,如果您查看它们的定义,它们是:
instance Monad [] where
xs >>= f = [y | x <- xs, y <- f x]
return x = [x]
所以对于源列表中的每个元素都>>=
适用f
,然后将返回列表的每个元素插入到结果列表中。
return x
只返回一个包含x
所以return (f a)
返回一个列表的单例列表[f a]
。然后将这些单个元素列表中的每一个组合起来(>>=)
以创建输出列表。
列表是 a monad
,因此给定 map 的签名:
map :: (a->b) -> [a] -> [b]
和 liftMM 的签名
liftMM :: Monad m => (a -> b) -> m a -> m b
那[]
是m
这意味着对于列表 liftMM
和map
做同样的事情。