Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
产生固定长度列表的笛卡尔积(haskell方法)_Haskell - Fatal编程技术网

产生固定长度列表的笛卡尔积(haskell方法)

产生固定长度列表的笛卡尔积(haskell方法),haskell,Haskell,我想创建一个固定长度的元素[0,1]序列,例如4,这样它会生成一个包含所有[0,1]组合的元素列表 我用命令式编程方法解决了这个问题: Prelude > let base = [1, 0] Prelude > [[x0, x1, x2, x3] | x0 <- base, x1 <- base, x2 <- base, x3 <- base] [[1,1,1,1],[1,1,1,0],[1,1,0,1], ... [0,0,0,0]] 我认为这是可以改进的

我想创建一个固定长度的元素[0,1]序列,例如4,这样它会生成一个包含所有[0,1]组合的元素列表

我用命令式编程方法解决了这个问题:

Prelude > let base = [1, 0]
Prelude > [[x0, x1, x2, x3] | x0 <- base, x1 <- base, x2 <- base, x3 <- base]
[[1,1,1,1],[1,1,1,0],[1,1,0,1], ... [0,0,0,0]]
我认为这是可以改进的

做这件事的惯用方法是什么?

序列工作原理:

但序列和复制的配对已经有了一个名称:

Prelude> import Control.Monad
Prelude Control.Monad> replicateM 4 [1,0]
[[1,1,1,1],[1,1,1,0],[1,1,0,1],[1,1,0,0],[1,0,1,1],[1,0,1,0],[1,0,0,1],[1,0,0,0],[0,1,1,1],[0,1,1,0],[0,1,0,1],[0,1,0,0],[0,0,1,1],[0,0,1,0],[0,0,0,1],[0,0,0,0]]
因为序列正在做所有有趣的工作,让我们仔细看看它。

sequence :: Monad m => [m a] -> m [a]
sequence [] = return []
sequence (x:xs) = do
    x'  <- x
    xs' <- sequence xs
    return (x':xs')
这只是把责任推给了concatMap,但也许现在它开始变得更有意义了

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap _ [] = []
concatMap f (x:xs) = f x ++ concatMap f xs
我不知道这有多大帮助,但值得记住

可能更有用的是将序列的类型签名专门化为m~[]:

在这种特定的情况下,序列实际上可以更好地重命名为序列。它创建所有序列,包括从每个内部列表中选择一个元素。

序列工作:

但序列和复制的配对已经有了一个名称:

Prelude> import Control.Monad
Prelude Control.Monad> replicateM 4 [1,0]
[[1,1,1,1],[1,1,1,0],[1,1,0,1],[1,1,0,0],[1,0,1,1],[1,0,1,0],[1,0,0,1],[1,0,0,0],[0,1,1,1],[0,1,1,0],[0,1,0,1],[0,1,0,0],[0,0,1,1],[0,0,1,0],[0,0,0,1],[0,0,0,0]]
因为序列正在做所有有趣的工作,让我们仔细看看它。

sequence :: Monad m => [m a] -> m [a]
sequence [] = return []
sequence (x:xs) = do
    x'  <- x
    xs' <- sequence xs
    return (x':xs')
这只是把责任推给了concatMap,但也许现在它开始变得更有意义了

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap _ [] = []
concatMap f (x:xs) = f x ++ concatMap f xs
我不知道这有多大帮助,但值得记住

可能更有用的是将序列的类型签名专门化为m~[]:


在这种特定的情况下,序列实际上可以更好地重命名为序列。它创建所有序列,包括从每个内部列表中选择一个元素。

Ha,我知道有一种Haskell方法,谢谢!你能告诉我为什么我们需要单子吗?@Robin-well,[]已经是单子的一个实例了。没有列表很难解决列表问题。至于控制的导入,Monad,这只是因为那是保存replicateM的地方。谢谢。看来我需要多读一些关于单子的章节。哈,我知道有一个哈斯克尔的方法,谢谢!你能告诉我为什么我们需要单子吗?@Robin-well,[]已经是单子的一个实例了。没有列表很难解决列表问题。至于控制的导入,Monad,这只是因为那是保存replicateM的地方。谢谢。看来我需要多读一些关于单子的章节。