Jean-Bernard Pellerin
Jean-Bernard Pellerin

Reputation: 12670

haskell division type mismatch?

I'm new to Haskell and I'm trying to implement a calculator for a homework. I am stuck at a spot where I need to perform division on two values and I think the issue is that their type cannot be inferred or needs to be declared/converted. I'm trying to learn how to fix this myself but any insights along the way would be helpful.

Here is the code:

data Value e = OK e | Error String deriving (Eq)

-- assuming we know how to type e can be shown, i.e. Show e, then
-- we know how to show a Value e type
instance (Show e) => Show (Value e) where
    show (OK x) = (show x)
    show (Error s) = "ERROR: " ++ s

type Token = String
type Result = Value Int
type Intermediate = [ (Value Int) ]

-- an algebra is a things that knows about plus and times
class Algebra a where
    plus :: a -> a -> a
    times :: a -> a -> a
    subtraction :: a -> a -> a
    division :: a -> a-> a

-- assuming that we know how to + and * things of type e, (i.e.
-- we have Num e, then we have algebra's over Value e 
instance (Num e) => Algebra (Value e) where
    plus (OK x) (OK y) = (OK (x+y))
    times (OK x) (OK y) = (OK (x*y))
    subtraction (OK x) (OK y) = (OK (x-y))
    division (OK x) (OK 0) = (Error "div by 0")
    division (OK x) (OK y) = (OK (x `div` y))   <-- this is line 44 that it complains about

Here is the error when I try running the program via ghci test.hs

test.hs:44:34:  
    Could not deduce (Integral e)  
      from the context (Algebra (Value e), Num e)  
      arising from a use of `div' at test.hs:44:34-42  
    Possible fix:  
      add (Integral e) to the context of the instance declaration  
    In the first argument of `OK', namely `(x `div` y)'  
    In the expression: (OK (x `div` y))  
    In the definition of `division':  
        division (OK x) (OK y) = (OK (x `div` y))  

There is more code to this, I thought I'd leave it out for clarity, but I can always edit it in if this is unclear otherwise.

Upvotes: 2

Views: 3346

Answers (2)

Anon.
Anon.

Reputation: 59993

div only operates on Integral values (only Int or Integer in the standard Prelude). Float and Double support division with the / operator, but the root of your problem is that the Num typeclass doesn't actually mandate a division operation of any kind.

Which makes sense - there are plenty of number collections that we might want to make instances of Num where multiplication is irreversible - a division operation would be essentially meaningless.

Upvotes: 3

ephemient
ephemient

Reputation: 204778

div :: (Integral a) => a -> a -> a
(/) :: (Fractional a) => a -> a -> a

Num a does not imply either Integral a nor Fractional a (though the inverse applies, of course). If you want to use div, you'll have to supply something at least as restrictive as an Integral a context.

Upvotes: 8

Related Questions