我目前正在处理Wiki上的 99 Haskell问题。话虽如此,我正在做问题编号 26 ,这需要一个程序,可以在给定的集合中写入与 n 元素的所有组合。我用大量的功能完成了我的实现,程序似乎是正确的。但我的问题不是来自于此,而是来自Haskell Wiki的其中一个解决方案
Selenium::WebDriver::Error::WebDriverError: unable to connect to chromedriver 127.0.0.1:9516
我了解combinations :: Int -> [a] -> [[a]]
combinations 0 _ = [ [] ]
combinations n xs = [ y:ys | y:xs' <- tails xs
, ys <- combinations (n-1) xs']
已针对函数 y:xs
提供的每个列表进行解析,从而生成可能值的列表,但我无法理解tails
值为ys
,以便y:ys
为我提供所有正确的解决方案。
另一个更重要的问题是为什么这两个表达式会产生不同的结果?
[xs | y:xs <- tails [1,2,3]]
[[2,3],[3],[]]
[xs | y:xs <- tails [1,2,3], z <- xs]
[[2,3],[2,3],[3]]
它们可能没有任何实际用途,但它们向我展示了一个Haskell初学者,这是一种非常奇怪的行为。为什么应用z <- xs
会更改xs
的值?
答案 0 :(得分:3)
由于comprehension desugaring rules,它们的结果不同。如果我们有
[ expression | a <- as, b <- bs ]
然后我们会得到
concatMap (\a -> concatMap (\b -> [expression]) bs) as
即使b
中未使用expression
,我们仍然会有更多元素。例如,concatMap (const [1]) [1..10]
将导致replicate 10 1
。因此,如果您在理解中添加另一个列表,则更改concatMap
的数量,因此也更改输出的数量(除非列表中只包含一个元素):
[a | a <- [1..10]] -- results in [1..10]
[a | a <- [1..10], _ <- [1,2]] -- results in [1,1,2,2,3,3,4,4,...,9,9,10,10]
[a | _ <- [1,2], a <- [1..10]] -- results in [1..10] ++ [1..10]
答案 1 :(得分:2)
代码
combinations n xs = [ y:ys | y:xs' <- tails xs
, ys <- combinations (n-1) xs']
读作:从n
选择xs
个元素,选择y
中的任意xs
,并将y
之后的元素尾部命名为{ {1}}。然后递归选择xs'
中的n-1
元素,命名任何此类选项xs'
。结果由可以以这种方式生成的所有ys
形成。
说服自己这个算法确实采取了所有可能的选择(确切地说:所有选择都遵循原始列表y:ys
给出的排序)。
请注意一些正确处理的极端情况。
首先,在xs
内,我们还会找到空尾tails xs
,但这会被忽略,因为它不是[]
形式。
然后,尾部y:xs'
可能比xs'
元素短。在这种情况下,n-1
会找到ys <- combinations (n-1) xs'
的零选项,因此没有&#34;输出&#34;将为此ys
生成。
最后,关于你的最后一个问题。考虑这个例子:
xs'
[ 42 | x <- [1,2,3 ] ] == [ 42, 42, 42 ]
的值不会影响x
的值,因为42
是常量,但它会影响其多样性。这与命令行循环42
非常相似,它会多次产生输出。