Haskell错误:"无法从文字'0'和#34;中推断出(Eq a);

时间:2014-10-19 22:37:02

标签: haskell winghci

我使用了本文档底部提供的代码: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”,但后来卡住了。

1 个答案:

答案 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]无需投诉即可编译。但正如我所说,这不是很好。