对于 real-world-frege 项目,我从 real-world-haskell 进行了练习,任务是为列表创建一个长度函数,并将其与内部长度函数进行比较。
我提出的解决方案在https://github.com/Dierk/Real_World_Frege/blob/master/realworld/chapter3/I_Exercise_1.fr
它的牛肉是:
mylength :: [a] -> Int
mylength (_:xs) = 1 + (mylength xs)
mylength [] = 0
-- optLength uses tail recursion and forces eager argument evaluation
optLength xs = privateLength xs 0 where
privateLength (_:rest) !count = privateLength rest (count + 1)
privateLength [] !count = count
main _ = do
assert (mylength []) (length []) "empty"
assert (mylength [0]) (length [0]) "one element"
-- assert (mylength [0..30_000]) (length [0..30_000]) "many elements lead to stack overflow"
assert (optLength [0..1_000_000]) (length [0..1_000_000]) "optLength can do a little more"
assert (optLength [0..10_000_000]) (length [0..10_000_000]) "this takes 40 seconds (20 s each)"
-- println (length [0..100_000_000]) -- never stops
对于 100 万个条目以下的列表,我的和内部长度函数都可以正常工作,在 10 M 时会变得非常慢,并且对于 100 M 似乎根本不会停止。
Frege 的内部长度函数(不是 Haskell 的)似乎有一个低于 1 亿的上限。是这样吗?