Haskell,list comprehension输出空列表。为什么呢?

时间:2018-03-11 21:54:47

标签: haskell list-comprehension evaluation

[x:ys | x<-[1,2], ys<-[]]

以上代码输出[]。我认为它应该输出[1,2]

那么我对Haskell评估的错误是什么?

2 个答案:

答案 0 :(得分:3)

您的期望有两个问题:

  1. x:ys始终会创建一个新列表; x:[] == [x],而不是x:[] == x
  2. 即使x:[] == x,事实仍然是ys <- []未将名称ys分配给空列表;它将ys分配给空列表中的包含值(当然,没有这样的值可以分配给ys)。
  3. 您可以将ys <- []更改为ys <- [[]],在这种情况下,您将获得

    > [x:ys | x<-[1,2], ys<-[[]]]
    [[1], [2]]
    

    但是如果你想要[1,2],那么简单的列表理解就是

    > [x | x <- [1,2]]
    [1,2]
    

    没有涉及其他列表,因为您不希望列表列表作为答案。

答案 1 :(得分:2)

列表推导表达嵌套循环:

[x:ys | x<-[1,2], ys<-[]]
 ==
do { x<-[1,2] ; do { ys<-[] ; return (x:ys) } }
 ==
{ for each x in [1,2]: { for each ys in []: yield (x:ys) } }
 == 
{ { for each ys in []: yield (1:ys) }     
; { for each ys in []: yield (2:ys) }     
}
 == 
{ { for none: yield ... } ; { for none: yield ... } }
 == 
{ none ; none }
 == 
none.

这让人联想到矩阵乘法:

join [ {- for 1: -}  [ a,b,c   ],       [  1a, 1b, 1c,
       {- for 2: -}  [ d,e     ],   =      2d, 2e,
       {- for 3: -}  [ f,g,h,i ],          3f, 3g, 3h, 3i
        ]                                                 ]

因此,如果为第一个列表的每个元素生成的列表为空,则总列表也为空,因为concat [ [], [], [] ] == []

另请参阅:How does the List monad work in this example?