2017-08-19 24 views
1

我是Haskell的新手,正在尝试使用代数组来做一些事情。我的第一个功能就是执行一个操作和一个集合,并通过在同一对集合的成员上执行该操作来查找集合中的所有成员。这是我的代码如下: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] 

谁能告诉我为什么发生这种情况,或者我做了一些愚蠢的事情?

回答

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]的所有元素:命名当前元素的,然后在列表中[4,5,6]所有元素:名称列表中也有当前元素(并因此忘记了以前的变种)并返回那些a s“。

上面的代码是因此相当于

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

或任何其它名称而不是_

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

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

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

+0

啊,谢谢澄清。我来自数学背景,思维列表理解与集合定义相同。 – user2461616

3

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

打开-Wall的警告应该会发现此问题。

您可以改为使用[a | a <- xs, elem a combSet]来检查a是否发生在combSet的内部。