有没有办法让 "preserve" 结果变成 Haskell?
Is there a way to "preserve" results in Haskell?
我是 Haskell 的新手,我知道它(基本上)是一种纯函数式语言,其优点是函数的结果不会在多次评估中发生变化。鉴于此,我很困惑为什么我不能轻松地标记一个函数,使其记住其第一次评估的结果,并且不必在每次需要其值时再次评估。
在 Mathematica, for example, there is a simple idiom 中完成此操作:
f[x_]:=f[x]= ...
但在 Haskell 中,我发现的最接近的是 something like
f' = (map f [0 ..] !!)
where f 0 = ...
f n = f' ...
除了不太清楚(并且显然仅限于 Int
参数?)之外,它(似乎)不会在交互式会话中保留结果。
诚然(而且很明显),我不明白这里到底发生了什么;但天真地,Haskel 似乎应该在函数定义级别有一些方法
- 利用它的函数是函数这一事实,并在计算结果后跳过对结果的重新计算,并且
- 表示希望使用简单明了的习惯用法在函数定义级别执行此操作。
有什么方法可以在 Haskell 中完成我所缺少的吗?我理解(有点)Haskell 不能将评估存储为 "state",但为什么它不能简单地(实际上)将评估函数重新定义为它们的计算值?
这源于 this question,其中缺少此功能会导致糟糕的性能。
使用合适的库,例如MemoTrie。
import Data.MemoTrie
f' = memo f
where f 0 = ...
f n = f' ...
这几乎不亚于 Mathematica 版本,是吗?
关于
“why can't it simply (in effect) redefine evaluated functions to be their computed value?”
嗯,总的来说不是那么容易。这些值必须存储在某个地方。即使对于 Int
值函数,您也不能只分配一个包含所有可能值的数组——它不适合内存。列表解决方案仅有效,因为 Haskell 是惰性的,因此允许无限列表,但这并不是特别令人满意,因为查找是 O(n ).
对于其他类型,这简直是无望的——你需要以某种方式对角化一个过度可数的无限域。
你需要一些更聪明的组织。我不知道 Mathematica 是如何做到这一点的,但它可能使用了很多“专有魔法”。对于任何输入,我不太确定它是否真的按照您想要的方式工作。
Haskell 幸运的是有类型 classes,这些允许你准确地表达一个类型需要什么才能快速记忆。 HasTrie就是这样一个class.
我是 Haskell 的新手,我知道它(基本上)是一种纯函数式语言,其优点是函数的结果不会在多次评估中发生变化。鉴于此,我很困惑为什么我不能轻松地标记一个函数,使其记住其第一次评估的结果,并且不必在每次需要其值时再次评估。
在 Mathematica, for example, there is a simple idiom 中完成此操作:
f[x_]:=f[x]= ...
但在 Haskell 中,我发现的最接近的是 something like
f' = (map f [0 ..] !!)
where f 0 = ...
f n = f' ...
除了不太清楚(并且显然仅限于 Int
参数?)之外,它(似乎)不会在交互式会话中保留结果。
诚然(而且很明显),我不明白这里到底发生了什么;但天真地,Haskel 似乎应该在函数定义级别有一些方法
- 利用它的函数是函数这一事实,并在计算结果后跳过对结果的重新计算,并且
- 表示希望使用简单明了的习惯用法在函数定义级别执行此操作。
有什么方法可以在 Haskell 中完成我所缺少的吗?我理解(有点)Haskell 不能将评估存储为 "state",但为什么它不能简单地(实际上)将评估函数重新定义为它们的计算值?
这源于 this question,其中缺少此功能会导致糟糕的性能。
使用合适的库,例如MemoTrie。
import Data.MemoTrie
f' = memo f
where f 0 = ...
f n = f' ...
这几乎不亚于 Mathematica 版本,是吗?
关于
“why can't it simply (in effect) redefine evaluated functions to be their computed value?”
嗯,总的来说不是那么容易。这些值必须存储在某个地方。即使对于 Int
值函数,您也不能只分配一个包含所有可能值的数组——它不适合内存。列表解决方案仅有效,因为 Haskell 是惰性的,因此允许无限列表,但这并不是特别令人满意,因为查找是 O(n ).
对于其他类型,这简直是无望的——你需要以某种方式对角化一个过度可数的无限域。
你需要一些更聪明的组织。我不知道 Mathematica 是如何做到这一点的,但它可能使用了很多“专有魔法”。对于任何输入,我不太确定它是否真的按照您想要的方式工作。
Haskell 幸运的是有类型 classes,这些允许你准确地表达一个类型需要什么才能快速记忆。 HasTrie就是这样一个class.