我正在做一个涉及使用数值方法来解决微分方程的问题,并认为这可能是学习一些基本Haskell的好机会.我有以下重现关系:
和初始条件u(x, 0) = x^2.我将这些翻译成Haskell(从特定问题中为a,b,c,h和k输入适当的值,并注意到u_ij被定义为u(i*h, j*k)):
u :: (Floating a, Eq a) => a -> a -> a
u x 0 = x*x
u x t = a*k / b*h * (u (x-h) (t-k))
+ (1 - (3*k/2*h))*(u x (t-k))
+ k/b * cos x
where
a = 3
b = 2
k = 0.1
h = 0.2
main = putStrLn (show (u 1 0.5))
Run Code Online (Sandbox Code Playgroud)
这似乎无限期地运行.我最好猜测为什么浮点表示意味着u x 0模式永远不会匹配.我习惯在其他语言中处理这个问题的方法是检查值之间的绝对差异是否在某个合适的epsilon中,但这似乎不适用于模式匹配.因此,浮点和模式匹配似乎从根本上是不兼容的.这可能是一个问题,如果是这样的话,在这样的情况下,有没有一种规范的方法来避免这种情况?
事实证明,解决方案是进一步阅读教程并使用守卫而不是模式匹配;他们使针对 epsilon 的检查变得非常简单:
u :: (Floating a, Ord a) => a -> a -> a
u x t
| abs t <= 0.1 = x*x
| otherwise = a*k / b*h * (u (x-h) (t-k))
+ (1 - (3*k/2*h))*(u x (t-k))
+ k/b * cos x
where
a = 3
b = 2
k = 0.1
h = 0.2
main = putStrLn (show (u 1 0.5))
Run Code Online (Sandbox Code Playgroud)
很快给出答案。