【问题标题】:Haskell error: "Could not deduce (Eq a) arising from the literal ‘0’"Haskell 错误:“无法从字面量‘0’推导出 (Eq a)”
【发布时间】:2014-10-19 22:37:02
【问题描述】:

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

【问题讨论】:

    标签: haskell winghci


    【解决方案1】:

    GHC 的“可能的修复”消息通常具有很大的误导性,但这一消息是正确的。为什么不试试呢?

    可能的修复:将(Eq a) 添加到实例声明的上下文中

    instance (Fractional a, Eq a) => Fractional [a] where
      ...
    

    这是必需的,因为某些 Num 实例可能不允许相等比较(事实上 this 实例是一个很好的例子,因为在有限时间内永远无法证明无限列表相等!)但是当编写模式(0:fs) / (0:gs) -> ...,您需要进行相等检查以确认头部实际上为零。列表当然有一个 Eq 实例,但实际上这些不是您正在处理的一般列表,而是 总是无限列表(否则这些模式是不穷尽的),因此您应该使用新类型包装器没有 Eq 实例代替,就像

    newtype Series a = Series {getSeries :: [a]}
    

    In þe olden days, Eq used to be a superclass of Num,所以[a] 可以毫无怨言地编译。但正如我所说,这并不是很好。

    【讨论】:

    • 我尝试了类似的东西,但现在很幸运,对不起,我是新手。但你的提议有效。我修复了这样的最后一个错误: main :: IO () main = print $ (iszero 30 test1) && (iszero 30 test2) 这是正确的吗?
    • 看起来不错。如果它不起作用,那是与您最初的问题完全无关的问题,如果您无法解决,请发布另一个问题。
    猜你喜欢
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    • 2016-06-30
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多