我最近在学习Haskell,和正在学习SICP的朋友聊天时,我们想比较一下Common Lisp和Scheme,所以我决定尝试将练习1.29翻译成Haskell作为练习。
此练习使用表示数学求和函数Sigma的函数sigma。该函数接受一个函数f,用于应用于每个项,一个下限,一个用于获取下一个项的函数,并且一个上限。它返回应用于每个项的f的总和。
simpsonIntegral应该使用Simpson法则来使用“精度”n近似计算函数f在范围[a,b]上的积分。 我无法让这个函数正常工作,因为似乎有些关于涉及类型的东西我不明白。
这段代码将在ghc 6.12.1版本中编译,但是simpsonIntegral将会被赋予(Integral a, Fractional a)这样一个没有任何意义的类型上下文,而且一旦调用它,该函数就会失效。 我曾经让它工作过,但我所做的显然是一个Hack,我想问问在这里应该如何惯用地处理它。
应该如何惯用地处理h中需要的整数 -> 分数/实数转换? 我读了很多东西,但没有什么是明显和干净的。
sigma :: (Ord a, Num b) => (a -> b) -> a -> (a -> a) -> a -> b
sigma f a next b = iter a 0
where
iter current acc | current > b = acc
| otherwise = iter (next current) (acc + f current)
simpsonIntegral f a b n = 1.0 * (h / 3) * (sigma simTerm 0 (1+) n)
where
h = (b - a) / n
simTerm k = (yk k) * term
where
yk k = f (a + h * k)
term =
case k of
0 -> 1
1 -> 1
otherwise -> if odd k then 4 else 2
fromIntegral
在其返回类型b
中具有多态性,即允许b
(返回类型)为Num
类型类的成员的任何数据类型。虽然Num
类型类不提供除法,但是一些作为该类型类成员的数据类型确实提供了除法,例如Double
。 - yfeldblum