我使用了本文档底部提供的代码:http://www.cs.dartmouth.edu/~doug/pearl.ps.gz
import Data.Ratio
infixl 7 .*
default (Integer, Rational, Double)
-- constant series
ps0, x:: Num a => [a]
ps0 = 0 : ps0
x = 0 : 1 : ps0
-- arithmetic
(.*):: Num a => a->[a]->[a]
c .* (f:fs) = c*f : c.*fs
instance Num a => Num [a] where
negate (f:fs) = (negate f) : (negate fs)
(f:fs) + (g:gs) = f+g : fs+gs
(f:fs) * (g:gs) = f*g : (f.*gs + fs*(g:gs))
fromInteger c = fromInteger c : ps0
instance Fractional a => Fractional [a] where
recip fs = 1/fs
(0:fs) / (0:gs) = fs/gs
(f:fs) / (g:gs) = let q = f/g in
q : (fs - q.*gs)/(g:gs)
-- functional composition
compose:: Num a => [a]->[a]->[a]
compose (f:fs) (0:gs) = f : gs*(compose fs (0:gs))
revert::Fractional a => [a]->[a]
revert (0:fs) = rs where
rs = 0 : 1/(compose fs rs)
-- calculus
deriv:: Num a => [a]->[a]
deriv (f:fs) = (deriv1 fs 1) where
deriv1 (g:gs) n = n*g : (deriv1 gs (n+1))
integral:: Fractional a => [a]->[a]
integral fs = 0 : (int1 fs 1) where
int1 (g:gs) n = g/n : (int1 gs (n+1))
expx, cosx, sinx:: Fractional a => [a]
expx = 1 + (integral expx)
sinx = integral cosx
cosx = 1 - (integral sinx)
instance Fractional a => Floating [a] where
sqrt (0:0:fs) = 0 : sqrt fs
sqrt (1:fs) = qs where
qs = 1 + integral((deriv (1:fs))/(2.*qs))
-- tests
test1 = sinx - sqrt(1-cosx^2)
test2 = sinx/cosx - revert(integral(1/(1+x^2)))
iszero n fs = (take n fs) == (take n ps0)
main = (iszero 30 test1) && (iszero 30 test2)
尝试运行时,我收到以下错误:
Prelude> :load pearl.hs
[1 of 1] Compiling Main ( pearl.hs, interpreted )
pearl.hs:22:10:
Could not deduce (Eq a) arising from the literal ‘0’
from the context (Num [a], Fractional a)
bound by the instance declaration at pearl.hs:20:10-39
Possible fix: add (Eq a) to the context of the instance declaration
In the pattern: 0
In the pattern: 0 : fs
In an equation for ‘/’: (0 : fs) / (0 : gs) = fs / gs
pearl.hs:28:17:
Could not deduce (Eq a) arising from the literal ‘0’
from the context (Num a)
bound by the type signature for
compose :: Num a => [a] -> [a] -> [a]
at pearl.hs:27:11-32
Possible fix:
add (Eq a) to the context of
the type signature for compose :: Num a => [a] -> [a] -> [a]
In the pattern: 0
In the pattern: 0 : gs
In an equation for ‘compose’:
compose (f : fs) (0 : gs) = f : gs * (compose fs (0 : gs))
pearl.hs:31:9:
Could not deduce (Eq a) arising from the literal ‘0’
from the context (Fractional a)
bound by the type signature for
revert :: Fractional a => [a] -> [a]
at pearl.hs:30:9-32
Possible fix:
add (Eq a) to the context of
the type signature for revert :: Fractional a => [a] -> [a]
In the pattern: 0
In the pattern: 0 : fs
In an equation for ‘revert’:
revert (0 : fs)
= rs
where
rs = 0 : 1 / (compose fs rs)
pearl.hs:49:15:
Could not deduce (Eq a) arising from the literal ‘0’
from the context (Fractional [a], Fractional a)
bound by the instance declaration at pearl.hs:48:10-37
Possible fix: add (Eq a) to the context of the instance declaration
In the pattern: 0
In the pattern: 0 : 0 : fs
In an equation for ‘sqrt’: sqrt (0 : 0 : fs) = 0 : sqrt fs
pearl.hs:57:1:
Couldn't match expected type ‘IO t0’ with actual type ‘Bool’
In the expression: main
When checking the type of the IO action ‘main’
Failed, modules loaded: none.
我已将“import ratio”更改为“import Data.Ratio”,但后来卡住了。
答案 0 :(得分:7)
GHC的“可能修复”消息通常非常具有误导性,但这一消息很明显。你为什么不试试呢?
可能的解决方法:将
(Eq a)
添加到实例声明的上下文
即
instance (Fractional a, Eq a) => Fractional [a] where
...
这是必要的,因为一些Num
实例可能不允许相等比较(实际上这个实例是一个很好的例子,因为无限列表在有限时间内永远不会被证明是相等的!)但是在编写模式(0:fs) / (0:gs) -> ...
时,需要进行相等检查以确认头部实际上为零。列表当然有一个Eq
实例,但实际上那些不是你正在处理的一般列表,但总是无限列表(否则这些模式是无穷无尽的),所以你应该使用newtype wrapper 而不是 Eq
实例,比如
newtype Series a = Series {getSeries :: [a]}
In þe olden days, Eq
used to be a superclass of Num
,因此[a]
无需投诉即可编译。但正如我所说,这不是很好。