Haskell 从上一个表达式创建一个没有指针的新表达式
我正在读这本书,试图找出这两种功能之间的区别: 此功能不会记忆中间编号:Haskell 从上一个表达式创建一个没有指针的新表达式,haskell,Haskell,我正在读这本书,试图找出这两种功能之间的区别: 此功能不会记忆中间编号: fib_mem :: Int -> Integer fib_mem = (map fib [0..] !!) where fib 0 = 1 fib 1 = 1 fib n = fib_mem (n-2) + fib_mem (n-1) 这不是: fib_mem_arg :: Int -> Integer fib
fib_mem :: Int -> Integer
fib_mem = (map fib [0..] !!)
where fib 0 = 1
fib 1 = 1
fib n = fib_mem (n-2) + fib_mem (n-1)
这不是:
fib_mem_arg :: Int -> Integer
fib_mem_arg x = map fib [0..] !! x
where fib 0 = 1
fib 1 = 1
fib n = fib_mem_arg (n-2) + fib_mem_arg (n-1)
作者试图解释如下:
运行fib_mem_arg时,除了非常小的参数外,任何东西都可以
确认它没有回忆录。即使我们可以看到地图上的谎言
[0..]不依赖于参数编号,可以记忆,
它不会是,,因为对函数应用参数将创建
不能隐式具有表达式指针的新表达式
来自以前的函数应用程序
他这句粗体字是什么意思?有人能给我举个简单的例子吗
为什么fib_mem
是一种常量应用形式
为什么fib\u mem
是一种恒定的应用形式
不是fib\u mem
,而是(映射fib[0..!!)
。这是因为它是一个部分应用的函数(!!)
。因此,它受内存保留的影响
(另见:)
由于该类型是单态的,因此即使在调用fib_mem
之间,它也会保留在内存中,实际上就像将fib[0..]映射到顶层一样,就像定义为
fib_mem_m :: Int -> Integer
fib_mem_m = (the_list !!)
where fib 0 = 1
fib 1 = 1
fib n = (the_list !! (n-2)) + (the_list !! (n-1))
the_list = map fib [0..]
fib_mem_p :: Num a => Int -> a
fib_mem_p = (the_list !!)
where fib 0 = 1
fib 1 = 1
fib n = (the_list !! (n-2)) + (the_list !! (n-1))
the_list = map fib [0..]
如果类型是多态的,则不可能浮到顶层,但在每次调用fib_mem
期间,它仍然会被保留,就像定义为
fib_mem_m :: Int -> Integer
fib_mem_m = (the_list !!)
where fib 0 = 1
fib 1 = 1
fib n = (the_list !! (n-2)) + (the_list !! (n-1))
the_list = map fib [0..]
fib_mem_p :: Num a => Int -> a
fib_mem_p = (the_list !!)
where fib 0 = 1
fib 1 = 1
fib n = (the_list !! (n-2)) + (the_list !! (n-1))
the_list = map fib [0..]
要查看差异,请在GHCi propt处对fib\u mem\u m 10000进行两次评估。第二次尝试将花费0秒。但是,fib_mem_p 10000
每次调用它都需要相同的时间。它仍然会像第一个一样快,所以仍然有记忆在那里进行,只是在通话之间没有保留
有了这种定义风格,在fib_mem_arg
中的完整应用程序也将被存储——正如上面的一样,不是在调用fib_mem_arg
之间,而是仅在每次调用期间
fib_mem_arg :: Num a => Int -> Integer -- or polymorphic, makes no difference
fib_mem_arg x = the_list !! x
where fib 0 = 1
fib 1 = 1
fib n = (the_list !! (n-2)) + (the_list !! (n-1))
the_list = map fib [0..]
但是这个粗体的句子是错误的!毕竟,
fib_mem 30000
和fib_mem 30001
都是函数对参数的应用,但后者隐含着指向前者的指针,因此无论您先做哪一个,都需要更长的时间。他们把矛头指向了错误的问题!另请参见:。@DanielWagner也许一个简单的例子也不错。为什么这是一个CAFz=(+)4
,而这不是z=\x->4+x
?有什么不同?根据定义,lambda表达式不是CAF。这就是wiki页面所说的。超级组合器对于我来说就像函数组合,例如h(g(fx))
。这是对的吗?为什么zn=[1..n]
不是CAFn
是一个绑定变量。h(g(f x))
是一个包含大量自由变量的表达式。您需要显示等式(定义)的左侧在z n=[1..n]
中,RHS上的n
取决于LHS上的n
,因此z
不是CAF。实际上,它可以先称为z5
,然后再称为z3
。这将是两个不同的值,而不是一个。