我想知道是否可以为 Bool 编写自己的 replicateM 实现 没有导入Monad模块的值?当我查看Haskell源代码时看起来确实很复杂,但我想知道该函数是如何工作的以及它应该是什么样的。
答案 0 :(得分:4)
replicateM
的定义是:
replicateM n x = sequence (replicate n x)
且replicate
的类型为Int -> a -> [a]
,因此例如replicate 4 True
为[True, True, True, True]
。
对于列表参数l = [True, False]
,replicate 2 l
为[[True, False], [True, False]]
。您的评论会询问replicate
和replicateM
之间的差异,您可以看到replicateM
使用replicate
,但随后会在结果上调用sequence
。
sequence
的类型是:
Monad m => [m a] -> m [a]
在此示例中,m
是列表,因此它将列表列表转换为另一个列表列表。
正如您所指出的,结果与调用replicate 2 l
不同。 sequence
的定义是:
sequence ms = foldr k (return []) ms
where
k m m' = do { x <- m; xs <- m'; return (x:xs) }
列表的do
块的工作方式类似于以下列表解析:
[[x:xs] | x <- m, xs <- m']
这是一个笛卡尔积,即通过在累加器中每个列表前面的m
的每个元素形成一个新列表。
考虑列表的一种方法是对非确定性选择进行建模,因此结果是输入列表中n
个选项的所有可能结果。
答案 1 :(得分:2)
我不是假装回答这个问题,但评论中缺乏格式化迫使我这样做。
简要版本replicateM n m
等同于
m >>= (\x1 -> m >>= (\x2 -> ... m >>= ( \xn -> return [x1,x2,...,xn])..))
或类似的
do
x1 <- m
x2 <- m
...
xn <- m
return [x1,x2,...,xn]
因此,列表replicateM
返回n
相等列表的笛卡尔积。对于Maybe
,它将是长度为n
或Nothing
的列表。对于“动作表演”monad,它将是执行n
动作的结果等。
答案 2 :(得分:1)
实施replicateM
的一种方法是:
replicateM n = sequence . replicate n
这有助于您理解吗?当然,棘手的部分在于sequence
的操作,其具有以下有趣的类型:
sequence :: Monad m => [m a] -> m [a]
因此,
replicateM 3 (Just 1)
= sequence (replicate 3 (Just 1))
= sequence ([Just 1, Just 1, Just 1])
= Just [1,1,1]