在伊德里斯实施Eratosthenes筛选

时间:2016-09-24 00:05:01

标签: primes sieve-of-eratosthenes idris

我正努力将我对Eratosthenes筛子的定义翻译成伊德里斯。这是迄今为止的功能:

%default total

eratos : Nat -> (l : List Nat) -> { auto ok: NonEmpty l } -> List Nat
eratos limit (prime :: rest) =
  if prime * prime > limit -- if we've passed the square root of n
  then prime :: xs         -- then we're done!
  -- otherwise, subtract the multiples of that prime and recurse
  else prime :: (eratos limit (rest \\ [prime^2,prime^2+prime..limit]))

main : IO ()
main = printLn $ eratos [2..100]

不幸的是,我收到了一个奇怪的编译器错误:

idris --build euler.ipkg
./E003.idr:18:18: error: expected: ")",
    dependent type signature
  else prime :: (eratos n (xs \\ [prime^2,prime^2+prime..n])) 

为什么编译器要查找类型签名?

1 个答案:

答案 0 :(得分:1)

我能够实现如下:

eratos : Nat -> (l : List Nat) -> List Nat
eratos _ [] = []
eratos limit (prime :: rest) =
  if prime * prime > limit -- if we've passed the square root of n
  then prime :: rest       -- then we're done!
  -- otherwise, subtract the multiples of that prime and recurse
  else prime :: eratos limit (rest \\ [(prime*prime),(prime*prime+prime)..limit])

通过此实现,类型检查器会考虑此功能"覆盖"。

最理想的情况是,我们不需要第一种情况,并且可以将输入限制为列表长度为> = 1的情况。但是,很难向编译器显示该列表永远不会为null或者这个函数的第二个参数在每次递归调用时结构变小。如果有人有任何建议,请将其添加为评论或其他答案!