【问题标题】:Implementing the Sieve of Eratosthenes in Idris在伊德里斯实施埃拉托色尼筛
【发布时间】:2016-09-24 00:05:01
【问题描述】:

我正在努力将我对 Eratosthenes 筛的定义翻译成 Idris。这是到目前为止的功能:

%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])) 

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

【问题讨论】:

  • 没有(^)函数。你需要一些括号:[prime*prime,(prime*prime+prime) .. limit]

标签: primes sieve-of-eratosthenes idris


【解决方案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 或者这函数的第二个参数在每次递归调用时在结构上变得更小。如果有人有建议,请将它们添加为 cmets 或其他答案!

【讨论】:

  • 您能否添加一些Empirical Orders of Growth 数据? Idris 是否有“有序列表”类型,所以 `\` 会很有效吗?
  • @WillNess 我真的不知道如何,欢迎你编译我的代码并尝试。
  • 它只需要测量例如以下素数的时钟时间。 10,000 和 20,000 以下(或任何其他对,所以时间大约是 10 秒,比如说)。我真的不想为此安装 Idris。
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-08
相关资源
最近更新 更多