过滤器挂起无限列表

时间:2016-12-02 09:17:13

标签: haskell

我有这段代码

isPrime x = x > 0 && filter divisible [1..x] == [1,x]
where divisible y = x `mod` y == 0

primes = filter isPrime [1..]

定义无限的素数列表。

所有这些案例都按预期运作:

*Main> take 10 primes
[2,3,5,7,11,13,17,19,23,29]

*Main> take 10 $ filter odd primes
[3,5,7,11,13,17,19,23,29,31]

然而

*Main> take 10 $ filter even primes
[2

挂起并且不会继续。我不知道为什么...... 我重新启动了ghci并且问题仍然存在。 我使用的是ghc 8.0.1。

我的包裹:

C:\projects\littlethings\prime>ghc-pkg list
C:/Program Files/Haskell Platform/8.0.1\lib\package.conf.d
    Cabal-1.24.0.0
    GLURaw-2.0.0.1
    GLUT-2.7.0.7
    HTTP-4000.3.3
    HUnit-1.3.1.1
    ObjectName-1.1.0.1
    OpenGL-3.0.0.2
    OpenGLRaw-3.1.0.0
    QuickCheck-2.8.2
    StateVar-1.1.0.4
    Win32-2.3.1.1
    array-0.5.1.1
    async-2.1.0
    attoparsec-0.13.0.2
    base-4.9.0.0
    binary-0.8.3.0
    bytestring-0.10.8.1
    case-insensitive-1.2.0.6
    containers-0.5.7.1
    deepseq-1.4.2.0
    directory-1.2.6.2
    fgl-5.5.2.3
    filepath-1.4.1.0
    fixed-0.2.1.1
    (ghc-8.0.1)
    ghc-boot-8.0.1
    ghc-boot-th-8.0.1
    ghc-prim-0.5.0.0
    ghci-8.0.1
    half-0.2.2.3
    hashable-1.2.4.0
    haskeline-0.7.2.3
    haskell-src-1.0.2.0
    hoopl-3.10.2.1
    hpc-0.6.0.3
    hscolour-1.24
    html-1.0.1.2
    integer-gmp-1.0.0.1
    mtl-2.2.1
    network-2.6.2.1
    network-uri-2.6.1.0
    parallel-3.2.1.0
    parsec-3.1.9
    pretty-1.1.3.3
    primitive-0.6.1.0
    process-1.4.2.0
    random-1.1
    regex-base-0.93.2
    regex-compat-0.95.1
    regex-posix-0.95.2
    rts-1.0
    scientific-0.3.4.6
    split-0.2.3
    stm-2.4.4.1
    syb-0.6
    template-haskell-2.11.0.0
    text-1.2.2.1
    tf-random-0.5
    time-1.6.0.1
    transformers-0.5.2.0
    unordered-containers-0.2.7.0
    vector-0.11.0.0
    xhtml-3000.2.1
    zlib-0.6.1.1

C:\Users\Hamburger\AppData\Roaming\ghc\x86_64-mingw32-8.0.1\package.conf.d
    (containers-0.5.8.1)
    data-ordlist-0.4.7.0
    lazyset-0.1.0.0
    memoize-0.8.1

1 个答案:

答案 0 :(得分:10)

只有2是素数甚至是。其他素数不均匀。 filter并不聪明。它试图找到下一个偶数素数,尽管它不存在。这就是你挂起的原因。

如果您想终止终止,您必须了解一般情况下无法解决问题(halting problem)。但无论如何你可以写近似值。

例如,它是非常简单的近似值:

funnyFilter p = go ntriesMax
  where
    go _ (x:xs) | p x = x : go ntriesMax xs
    go _     []       = []
    go 0      _       = []
    go n (_:xs)       = go (n - 1) xs
    ntriesMax = 10000