Search code examples
haskellwinghci

Haskell error: "Could not deduce (Eq a) arising from the literal ‘0’"


I used the code provided at the bottom of this document: 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)

When trying to run it, I get the following errors:

    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.

I've changed "import Ratio" to "import Data.Ratio", but then got stuck.


Solution

  • GHC's "possible fix" messages are often very misleading, but this one is spot on. Why didn't you try it?

    Possible fix: add (Eq a) to the context of the instance declaration

    i.e.

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

    This is needed because some Num instances may not allow equality comparison (in fact this instance is an excellent example, since the infinite lists can never be proven equal in finite time!) but when writing a pattern (0:fs) / (0:gs) -> ..., you need an equality check to confirm the head is in fact zero. Lists of course have an Eq instance, but really those aren't general lists you're dealing with but always-infinite lists (otherwise those patterns are inexhaustive), so you should use a newtype wrapper without Eq instance instead, like

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

    In þe olden days, Eq used to be a superclass of Num, so the [a] would compile without complaints. But as I said, this wasn't really good.