我想实现以下天真的(一阶)有限差分函数:
finite_difference :: Fractional a => a -> (a -> a) -> a -> a
finite_difference h f x = ((f $ x + h) - (f x)) / h
您可能知道,有一个微妙的问题:必须确保这一点,(x + h)
并且x
相差一个完全可表示的数字。否则,由于涉及灾难性取消这一事实,结果会产生巨大的错误(f $ x + h) - (f x)
(并且必须仔细选择h
,但这不是我的问题)。
在 C 或 C++ 中,问题可以这样解决:
volatile double temp = x + h;
h = temp - x;
并且volatile
修饰符禁用与变量有关的任何优化temp
,因此我们确信“聪明”的编译器不会优化掉这两行。
我对 Haskell 的了解还不够,不知道如何解决这个问题。恐怕
let temp = x + h
hh = temp - x
in ((f $ x + hh) - (f x)) / h
将被 Haskell(或它使用的后端)优化掉。我怎样才能得到volatile
这里的等价物(如果可能的话不牺牲懒惰)?我不介意 GHC 的具体答案。