无法理解列表理解

时间:2013-05-29 03:43:13

标签: haskell list-comprehension pythagorean

我刚刚开始学习haskell(字面意思,今晚!)而且我在理解列表推导的逻辑方面遇到了一些麻烦,更具体地说是<-运算符。 Learn You Some Haskell上的一个小例子查找长度小于10的所有元组:

ghci> let triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]

我最初的理解是这些都会一起增加,但在看到输出后我真的不理解这些列表的递增方法。另一个似乎让我得到的例子是:

ghci> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]

我真的很感激对这些的一点解释,感谢你对我缺乏耐克尔情报的耐心。

3 个答案:

答案 0 :(得分:20)

[称为“列表”,将|称为“for”,将<-称为“in”,将,称为“and”。

枚举以嵌套方式完成。 [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]真的是

for c from 1 to 10 step 1:
   for b from 1 to c step 1:
      for a from 1 to b step 1:
          if (a^2 + b^2 == c^2):
             emit (a,b,c)

在Haskell中,上述内容是通过以下翻译实现的

[1..10] >>= (\c->               -- (a function of 'c', producing ...
  [1..c]  >>= (\b->               -- (a function of 'b', producing ...
    [1..b]  >>= (\a->               -- (a function of 'a', producing ...
      if a^2+b^2==c^2 then [(a,b,c)] else []
      -- or: [(a,b,c) | a^2+b^2==c^2]
      )))

所以你真的可以在这里看到嵌套结构。 (>>=)也不是什么神秘的事。阅读>>=为“fed into”或“push through”,尽管其官方名称为“bind”。它被定义为(对于列表)为

(xs >>= f) = concatMap f xs = concat (map f xs)

f此处(按map)按顺序调用xs的每个元素。它必须生成列表,以便它们可以与concat结合使用。由于在[]上删除了空列表concat(例如concat [[1], [], [3]] == [1,3]),所有未通过测试的元素都会从最终输出中删除。


有关Haskell 98报告的完整翻译,请参阅section 3.11, List Comprehensions。通常,列表推导可以包含模式,而不仅仅是变量名称。理解

[e | pat <- ls, ...]  

翻译为

ls >>= (\x -> case x of pat -> [e | ...] ;
                        _   -> [] )

其中pat是某种模式,x是一个新变量。当模式不匹配时,会生成一个空列表(而不是运行时错误),并跳过x的元素ls。这对于附加的基于模式的过滤是有用的,例如, <{1}},[x | Just x <- ls, even x]Nothing的{​​{1}}被悄然忽略。

答案 1 :(得分:4)

[ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]表示,对于(a,b,c)的所有组合,其中a在[1..10]中,b在[1..10]中,c在[1..10]中]

如果你想要(1,1,1)(2,2,2)种类,你应该使用zipzip [1..10] [1..10]或3个列表,zip3 [1..10] [1..10] [1..10]

答案 2 :(得分:1)

我认为列表理解语法是Haskell尝试在语言中获得Set-builder notation。我们使用'['而不是'{'和'&lt; - '而不是'ε'。列表理解语法甚至可以generalized到任意monad。