自己的replicateM实现

时间:2014-01-26 20:52:02

标签: haskell

我想知道是否可以为 Bool 编写自己的 replicateM 实现 没有导入Monad模块的值?当我查看Haskell源代码时看起来确实很复杂,但我想知道该函数是如何工作的以及它应该是什么样的。

3 个答案:

答案 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]]。您的评论会询问replicatereplicateM之间的差异,您可以看到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,它将是长度为nNothing的列表。对于“动作表演”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]