我想了解有关Haskell函数的一些知识。
首先,这是以典型的“慢速”方式定义的斐波那契函数(即没有记忆且没有无限列表技巧的递归方法)
slowfib :: Int -> Integer
slowfib 0 = 0
slowfib 1 = 1
slowfib n = slowfib (n-2) + slowfib (n-1)
[接下来,是该书的规范记忆版本。 (因为我更喜欢!!运算符的前缀版本,所以它与Tutorials / books / etc中的典型示例稍有不同。)
最终成为带有参数的函数,并且在定义时不包含参数。memfib = (!!) (map fib [0..]) where fib 0 = 0 fib 1 = 1 fib k = memfib(k-2) + memfib(k-1)
上述解决方案使用(!!)运算符的部分应用,这是有道理的:我们希望memfib
到目前为止,一切都很好。现在,我以为我可以编写一个等效的记忆功能,在定义中does
包含一个参数,所以我这样做了:和memfib_wparams只是彼此的eta转换。我认为?)]memfib_wparam n = ((!!) (map fib [0..])) n where fib 0 = 0 fib 1 = 1 fib k = memfib_wparam(k-2) + memfib_wparam(k-1)
((在Lambda演算术语中,memfib
这可行,但是备忘录消失了。实际上,memfib_wparam
的表现甚至比showfib更差:不仅速度较慢,而且其内存使用量是其两倍多。)中使用的语法只是我在memfib中所做的语法糖,但显然不是。*Main> slowfib 30 832040 (1.81 secs, 921,581,768 bytes) *Main> memfib 30 832040 (0.00 secs, 76,624 bytes) *Main> memfib_wparam 30 832040 (2.01 secs, 2,498,274,008 bytes)
这里发生了什么?更重要的是,我对Haskell函数定义出错的更广泛理解是什么?我以为我在memfib_wparam
我试图了解有关Haskell函数的一些信息。首先,这是以典型的“慢”方式定义的斐波那契函数(即没有记忆的递归操作,也没有无限列表技巧)...
区别在于绑定fib
函数的时间。