Haskell 如何在列表中计算相关范围?

Haskell 如何在列表中计算相关范围?,haskell,list-comprehension,evaluation,Haskell,List Comprehension,Evaluation,我现在正在努力,我对中倒数第二个例子感到困惑 作为一种生成三元组的方法,表示所有边都是小于或等于10的整数的所有直角三角形,他给出了以下定义: rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2] rightTriangles=[(a,b,c)| c鉴于您有命令式编程的经验,简短的回答是:对于嵌套(伪代码),与此类似: >(c=1;c)让我们考虑两个更简

我现在正在努力,我对中倒数第二个例子感到困惑

作为一种生成三元组的方法,表示所有边都是小于或等于10的整数的所有直角三角形,他给出了以下定义:

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

rightTriangles=[(a,b,c)| c鉴于您有命令式编程的经验,简短的回答是:对于嵌套(伪代码),与此类似:


<代码> >(c=1;c)让我们考虑两个更简单的列表理解:

ex1 = [(a,b) | a <- [1..3], b <- [1..3]]

ex2 = [(a,b) | a <- [1..3], b <- [1..a]]
ex1 = concat [ [(a,b) | b <- [1..3]] | a <- [1..3] ]

ex2 = concat [ [(a,b) | b <- [1..a]] | a <- [1..3] ]
在第一个示例中,列表理解从
[1..3]
[1..3]
中提取所有可能的元素组合。但是,由于我们讨论的是列表,而不是集合,它的顺序很重要。因此,更详细地说,
ex1
真正的意思是:

  • a
    等于其列表中的每个可能值。
    • 对于
      a
      的每个值,让
      b
      为其列表中的每个可能值。
      • (a,b)
        是输出列表的一个元素
或者,换言之:“对于
a
的每个可能值,计算
(a,b)
对于
b
的每个可能值。”如果您查看结果的顺序,会发生以下情况:

  • 对于前三个元素,
    a
    等于
    1
    ,我们看到它与
    b
    的每个值成对出现
  • 对于接下来的三个元素,
    a
    等于
    2
    ,我们可以看到
    b
    的每个值
  • 最后,对于最后三个元素,
    a
    等于
    3
    ,我们可以看到
    b
    的每个值
  • 在第二种情况下,情况大致相同。但由于首先选择了
    a
    ,因此
    b
    可以依赖于它。因此:


  • 首先,
    a
    等于
    1
    ,我们看到它与
    b
    的每一个可能值都是成对的。正如你所说的
    b,这个答案有些让我不知所措,但由于第一个非常清晰的例子,我完全理解了核心概念。随着我在Haskell的进步,我会回到这一点上,并希望得到平衡更多信息。无论如何,谢谢你!整体回答很好!
    
    ex1 = [ (1,1), (1,2), (1,3)
          , (2,1), (2,2), (2,3)
          , (3,1), (3,2), (3,3) ]
    
    ex2 = [ (1,1),
          , (2,1), (2,2),
          , (3,1), (3,2), (3,3) ]
    
    ex1 = concat [ [(a,b) | b <- [1..3]] | a <- [1..3] ]
    
    ex2 = concat [ [(a,b) | b <- [1..a]] | a <- [1..3] ]
    
    ex1 = concatMap (\a -> [(a,b) | b <- [1..3]]) [1..3]
        = concatMap (\a -> concatMap (\b -> [(a,b)]) [1..3]) [1..3]
    
    ex2 = concatMap (\a -> [(a,b) | b <- [1..a]]) [1..3]
        = concatMap (\a -> concatMap (\b -> [(a,b)]) [1..a]) [1..3]
    
    rightTriangles =
      concatMap (\c ->
        concatMap (\b ->
          concatMap (\a ->
            if a^2 + b^2 == c^2
              then [(a,b,c)]
              else []
          ) [1..b]
        ) [1..c]
      ) [1..10]
    
    import Control.Monad (guard)
    
    rightTriangles = do c <- [1..10]
                        b <- [1..c]
                        a <- [1..b]
                        guard $ a^2 + b^2 == c^2
                        return (a,b,c)
    
    rightTriangles = do
      c <- [1..10]             -- For each `c` from `1` to `10`, ...
      b <- [1..c]              -- For each `b` from `1` to `c`, ...
      a <- [1..b]              -- For each `a` from `1` to `b`, ...
      guard $ a^2 + b^2 == c^2 -- If `a^2 + b^2 /= c^2`, then `continue` (as in C);
      return (a,b,c)           -- `(a,b,c)` is the next element of the output list.
    
    rightTriangles = do c <- [1..10]
                        b <- [1..c]
                        a <- [1..b]
                        if a^2 + b^2 == c^2
                          then return (a,b,c)
                          else [] -- or `mzero`