Haskell中的嵌套列表推导

时间:2014-12-01 23:26:44

标签: haskell nested list-comprehension

我正在关注此Haskell tutorial,并且是在高阶函数部分。它定义了一个名为chain的函数:

chain :: (Integral a) => a -> [a]
chain 1 = [1]
chain n
    | even n = n:chain (n `div` 2)
    | odd n = n:chain (n * 3 + 1)

有一项练习可以找到许多"链"长度超过15的人。他们这样做:

numLongChains :: Int  
numLongChains = length (filter isLong (map chain [1..100]))  
    where isLong xs = length xs > 15

我试图想出一个列表理解,而不是给我链的数量给我一个从[1..100]开始超过15的链的列表。到目前为止,我最接近的尝试是:

[ [ a | a <- chain b, length a > 15] | b <- [1..100]]

但我明白了:

<interactive>:9:14:
No instance for (Integral [a0]) arising from a use of `chain'
Possible fix: add an instance declaration for (Integral [a0])
In the expression: chain b
In a stmt of a list comprehension: a <- chain b
In the expression: [a | a <- chain b, length a > 15]

<interactive>:9:45:
    No instance for (Enum [a0])
      arising from the arithmetic sequence `1 .. 100'
    Possible fix: add an instance declaration for (Enum [a0])
    In the expression: [1 .. 100]
    In a stmt of a list comprehension: b <- [1 .. 100]
    In the expression:
      [[a | a <- chain b, length a > 15] | b <- [1 .. 100]]

<interactive>:9:46:
    No instance for (Num [a0]) arising from the literal `1'
    Possible fix: add an instance declaration for (Num [a0])
    In the expression: 1
    In the expression: [1 .. 100]
    In a stmt of a list comprehension: b <- [1 .. 100]

我甚至关闭了吗?尽管可能有更好的方法来解决这个问题,但我确实希望使用嵌套理解来解决这个问题。

1 个答案:

答案 0 :(得分:4)

你关闭了。您正在寻找:

[ a | b <- [1..10], let a = chain b, length a > 15 ]

表达式

[ [ a | a <- chain b, length a > 15] | b <- [1..100]]

有类型:

Integral [a] => [[[a]]]

这显然不是你想要的,但由于Haskell的多态数字文字,可能可能会检查是否有正确的定义。

在这种情况下,b被推断为某种类型的列表,这就是您看到错误的原因:

No instance for (Integral [a0]) ...

以下是关于如何推断类型的完整细分。

    来自b <- [1..100]
  1. 我们可以推断Enum b是约束
  2. 来自致电chain b
  3. 我们可以推断Integral b是约束
  4. 来自a <- chain b我们可以推断ab具有相同的类型
  5. 来自length a我们可以推断a是一个列表,例如a ~ [t]
  6. 因此,从(3)和(4)我们可以推断出b ~ [t],因此对于某种类型Integral [t]我们需要Enum [t]t

    为了进一步阐述(3),我们知道chain b是一个列表,例如[t]其中tb的类型。来自a <- chain b我们知道achain b的元素具有相同的类型,即a的类型也是t