有没有办法生成类似的东西:
list n = [[q1,..,qn]|q1 <- [1..5], .., qn <- [1..5]]
?
我有一个集合,例如 [1..5] 和一个数字 n,它决定了我的列表要处理多长时间。我想要的是这个长度为 n 的列表的列表,其中每个位置都在我给定的集合范围内。
例如:
list 2 = [[1,1],[1,2],[1,3],[1,4],[1,5],[2,1],...]
list 3 = [[1,1,1],[1,1,2]...]
有没有办法生成类似的东西:
list n = [[q1,..,qn]|q1 <- [1..5], .., qn <- [1..5]]
?
我有一个集合,例如 [1..5] 和一个数字 n,它决定了我的列表要处理多长时间。我想要的是这个长度为 n 的列表的列表,其中每个位置都在我给定的集合范围内。
例如:
list 2 = [[1,1],[1,2],[1,3],[1,4],[1,5],[2,1],...]
list 3 = [[1,1,1],[1,1,2]...]
如果我理解正确,您想要的是一个函数,给定n
列表,它会采用它们的叉积。例如,
cross [[1, 2, 3], [10, 20, 30]] = [[1, 10], [2, 10], [3, 10]
,[1, 20], [2, 20], [3, 20]
,[1, 30], [2, 30], [3, 30]]
有趣的是,这个函数已经存在,它被称为sequence
. 例如:
Prelude> sequence [[1, 2, 3]]
[[1],[2],[3]]
Prelude> sequence [[1, 2, 3], [10, 20, 30]]
[[1,10],[1,20],[1,30],[2,10],[2,20],[2,30],[3,10],[3,20],[3,30]]
Prelude> sequence [[1, 2, 3], [10, 20, 30], [100, 200, 300]]
[[1,10,100],[1,10,200],[1,10,300],[1,20,100],[1,20,200],[1,20,300],[1,30,100],[1,30,200],[1,30,300],[2,10,100],[2,10,200],[2,10,300],[2,20,100],[2,20,200],[2,20,300],[2,30,100],[2,30,200],[2,30,300],[3,10,100],[3,10,200],[3,10,300],[3,20,100],[3,20,200],[3,20,300],[3,30,100],[3,30,200],[3,30,300]]
这是怎么回事?好吧,记住 List 类型[]
是一个 monad,并且sequence
有 type sequence :: [m a] -> m [a]
;本质上,它使用 monadic 绑定组合了 monadic 值。当m
是列表类型时,它变为[[a]] -> [[a]]
。要查看它是如何工作的,请考虑以下代码:
do
a <- [1, 2, 3]
b <- [10, 20, 30]
return [a, b]
这相当于sequence
只对两个输入列表执行的操作。List bind( >>=
) 只是将给定flip concatMap
的return
值包装在一个列表中,所以这相当于
let aList = [1, 2, 3]
bList = [10, 20, 30]
flippedConcatMap = flip concatMap in
aList `flippedConcatMap` (\a ->
bList `flippedConcatMap` (\b -> [[a, b]]))
这本质上是一个嵌套的 for 循环。对于 中的每个值aList
,我们应用接受 的函数a
。此函数接受 中的每个值bList
,并应用接受 的函数,它只b
返回一个包含单个元素的列表[a, b]
。然后,两个“for 循环”(concatMaps)都获取它们生成的所有元素并将它们粘贴到一个列表中,因此所有[a, b]
列表都合并为一个,这会产生您在评估时在 GHCi 中看到的内容sequence [[1, 2, 3], [10, 20, 30]]
。