Reputation: 12670
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
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
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