Haskell根据给定的输入创建一个n元组

时间:2015-02-15 16:43:21

标签: list haskell

说得好,我对Haskell很新,试图解决问题(编程练习)我过来了。它说我应该创建一个函数

com :: Int -> [t] -> [[t]]

返回n个元素的所有可能选择,其中n和list分别是第一个和第二个参数。可以以不同的顺序再次拾取元素。结果就像:

com 2 [1,2,3] = [[1,1], [1,2]..[3,3]]

对于n = 1和n = 2的情况,我设法解决了这些情况。情况n = 1非常简单,对于n = 2的情况,我会使用连接并构建它。但是,我不明白它是如何成为n-ary并为所有人工作的。就像突然一个函数调用会像com 10 ...

一样

3 个答案:

答案 0 :(得分:5)

这是你想要的吗?

> sequence (replicate 3 "abc")
["aaa","aab","aac","aba","abb","abc","aca","acb","acc"
,"baa","bab","bac","bba","bbb","bbc","bca","bcb","bcc"
,"caa","cab","cac","cba","cbb","cbc","cca","ccb","ccc"]

以上内容利用了列表monad中sequence构建列表列表的笛卡尔积的事实。因此,我们可以简单地复制列表n次,然后获取产品。

(请注意,上面"abc"是charatcters列表的简写['a','b','c']

所以,解决方案可能是

com n xs = sequence (replicate n xs)

或等效地,正如Daniel Wagner在下面指出的那样,

com = replicateM

最后一点:我确实意识到这对于实际学习如何编程可能不是很有帮助。实际上,我从库中提取了两个“神奇”功能来解决任务。不过,它还显示了如何将问题简化为两个子问题:1)复制值n次和2)构建笛卡尔积。如果您不想使用该库,第二项任务本身就是一项很好的练习。您可能希望从以下开始解决这个问题:

sequence :: [[a]] -> [[a]]
sequence []     = [[]]
sequence (x:xs) = ...
       where ys = sequence xs

答案 1 :(得分:2)

首先:[]是列表构造函数,而不是元组。我不知道建立n元组元的任何一般方法。

但是,坚持列表,如果您已解决n = 1案例并解决了n = 2案例,请尝试用前者表达后者。然后根据n

概括为任何n-1
com n xs = concat [map (x:) (com (n-1) xs) | x <- xs ]

答案 2 :(得分:1)

更简洁的编写方式,但在尝试理解List非确定性并试图准确理解Haskell理解语法糖的真正含义时,可能更有用的是用do来编写符号:

com :: Int -> [a] -> [[a]]
com 0 _  = []
com 1 xs = [[x] | x <- xs]
com n xs = do
    x <- xs
    let ys = com (n - 1) xs
    map (x:) ys