Haskell列表理解谓词顺序

时间:2017-08-19 11:15:24

标签: haskell functional-programming list-comprehension

我对Haskell很新,我正在尝试用代数组做一些事情。我的第一个功能就是采取一个操作和一个集合,并找到可以通过在一对相同集合的成员上执行该操作而生成的集合的所有成员。这是我的代码:

group' f xs = [a | a <- xs, a <- combSet]
    where combSet = [f x y | x <- xs, y <- xs]

但是,此代码只返回combSet的成员集,忽略a <- xs谓词:

*Main> group' (*) [1, 2, 3, 4, 5]
[1,2,3,4,5,2,4,6,8,10,3,6,9,12,15,4,8,12,16,20,5,10,15,20,25,1,2,3,4,5,2,4,6,8,10,3,6,9,12,15,4,8,12,16,20,5,10,15,20,25,1,2,3,4,5,2,4,6,8,10,3,6,9,12,15,4,8,12,16,20,5,10,15,20,25,1,2,3,4,5,2,4,6,8,10,3,6,9,12,15,4,8,12,16,20,5,10,15,20,25,1,2,3,4,5,2,4,6,8,10,3,6,9,12,15,4,8,12,16,20,5,10,15,20,25]

但是当我将理解谓词的顺序切换到

group' f xs = [a | a <- combSet, a <- xs]
    where combSet = [f x y | x <- xs, y <- xs]

它返回正确的值,但列表比预期的要大:

*Main> group' (*) [1, 2, 3, 4, 5]
[1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]

有谁能告诉我为什么会这样,或者我做了些什么蠢事?

2 个答案:

答案 0 :(得分:5)

您没有谓词开头。您有两个列表,xscombSet,您可以从中获取元素。因此,让我们用一个更简单的例子检查行为:

example = [a | a <- [1,2,3], a <- [4,5,6]]

这将导致concat $ replicate 3 [4,5,6],即[4,5,6,4,5,6,4,5,6]。请注意,第一个列表中没有元素,后者绑定了a 阴影

我们可以将上面的代码作为“列表[1,2,3]中的所有元素:为当前元素a命名,然后为列表[4,5,6]中的所有元素命名:将列表中的当前元素命名为a (并忘记之前的变体)并返回a s。。

上面的代码等同于

example = [a | _ <- [1,2,3], a <- [4,5,6]]

或任何其他名称,而不是_

对于谓词,您需要Bool表达式,例如

evenNumbers = [a | a <- [1..100], even a]

在您的情况下,布尔表达式可能是a `elem` combSet

答案 1 :(得分:3)

[a | a <- xs, a <- combSet]相当于[a | x <- xs, a <- combSet],因为第一个a被第二个“遮蔽”。当存在相同标识符的嵌套重新定义时,这总是发生,例如,在\a -> ... (\a -> ....)

使用-Wall打开警告应该发现此问题。

您可以使用[a | a <- xs, elem a combSet]检查a内是否发生combSet