变量列表理解长度

Bul*_*aza 3 haskell list-comprehension

我正在通过列表推导生成列表列表,但我不知道如何通过使用参数使子列表的长度变量.以下输入是一个元组(first, second)和一个Integer z:

z = 1:

[[a] | a <- [first..second]]
Run Code Online (Sandbox Code Playgroud)

z = 2:

[[a, b] | a <- [first..second], b <- [first..second]]
Run Code Online (Sandbox Code Playgroud)

z = 3:

[[a, b, c] | a <- [first..second], b <- [first..second], c <- [first..second]]
Run Code Online (Sandbox Code Playgroud)

bhe*_*ilr 8

您可以使用replicateM此任务.它被定义为

replicateM :: Monad m => Int -> m a -> m [a]
replicateM n m = sequence (replicate n m)
Run Code Online (Sandbox Code Playgroud)

这里的连接是将列表理解转换为do符号:

[[a] | a <- [first..second]] == do
    a <- [first..second]
    return [a]

[[a, b] | a <- [first..second], b <- [first..second]] == do
    a <- [first..second]
    b <- [first..second]
    return [a, b]

[[a, b, c] | a <- [first..second], b <- [first..second], c <- [first..second]] == do
    a <- [first..second]
    b <- [first..second]
    c <- [first..second]
    return [a, b, c]
Run Code Online (Sandbox Code Playgroud)

为了更清楚,让我们替换[first..second]m:

do  let m = [first..second]
    a <- m
    b <- m
    c <- m
    return [a, b, c]
Run Code Online (Sandbox Code Playgroud)

所以在这里你可以看到,这m只是复制n时间,因此replicateM.让我们看看这些类型如何排列:

replicateM :: Monad m => Int -> m a -> m [a]

m ~ []

replicateM_List :: Int -> [a] -> [[a]]
Run Code Online (Sandbox Code Playgroud)

如果您需要在任意列表上执行此操作,而不仅仅是重复相同的列表,您可以使用sequence


And*_*ewC 5

TL; DR使用理解和折叠或与bheklilr的copyM建议一起使用

理解力和对折

您知道您正在使用列表理解功能,因此,让我们看看如何通过首先编写一个以所有可能的方式为列表值添加前缀的函数来递归地执行此操作。

ghci> prepend "123" ["first","second"]
["1first","1second","2first","2second","3first","3second"]
Run Code Online (Sandbox Code Playgroud)
prepend :: [a] -> [[a]] -> [[a]]
prepend xs yss = [x:ys| x<-xs, ys<-yss]
Run Code Online (Sandbox Code Playgroud)

现在,我们来创建列表列表,首先replicate :: Int -> a -> [a]用于复制列表n次,然后prepend通过折叠列表将每个副本复制到其他副本的前面:

lol :: [a] -> Int -> [[a]]
lol xs n = foldr prepend [[]] $ replicate n xs
Run Code Online (Sandbox Code Playgroud)
ghci> lol "ab" 3
["aaa","aab","aba","abb","baa","bab","bba","bbb"]
ghci> lol [1..3] 2
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
Run Code Online (Sandbox Code Playgroud)

我相信您可以弄清楚如何将其与一对(start, finish)参数一起使用。

复制M

正如评论bheklilr指出,我们可以import Control.Monad和GET

replicateM :: Monad m => Int -> m a -> m [a]
Run Code Online (Sandbox Code Playgroud)

如果您将其专门列出,您将获得

replicateM :: Int -> [a] -> [[a]]
Run Code Online (Sandbox Code Playgroud)

用你想要的做:

ghci> replicateM 2 [1..3]
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
Run Code Online (Sandbox Code Playgroud)

如果像我一样,您没有bheklilr那样聪明的头脑,则可以像这样用hoogle 搜索具有所需类型的函数([a] -> Int -> [[a]]在这种情况下),然后找出第三个函数replicateM。(droptake不这样做我们想要的。)