Reputation: 1829
I'm trying to understand haskell error messages, as they are confusing for novice programmer. The simplest example I could find is this:
Prelude> 1 + True
<interactive>:2:3:
No instance for (Num Bool)
arising from a use of `+'
Possible fix: add an instance declaration for (Num Bool)
In the expression: 1 + True
In an equation for `it': it = 1 + True
Why does compiler look for (Num Bool) regardless of parameter order? Why does it work after I define the following?
instance Num Bool where (+) a b = True;
[...]
Prelude> 1 + True
True
How can I make sure (+) can be applied to (Num Bool) only when second argument is also (Num Bool)?
Upvotes: 2
Views: 231
Reputation: 68152
You get this error message because both 1
and +
are polymorphic--they can both work for different types!
Take a look:
Prelude> :t 1
1 :: Num a => a
Prelude> :t (+)
(+) :: Num a => a -> a -> a
So both 1
and +
are meaningful for any type in the Num
class. So when you write 1 + Bool
, the 1
could actually be a Bool
, if Bool
had a Num
instance. In fact, you can do that yourself:
instance Num Bool where
fromInteger x = x /= 0
(+) = (&&)
...
Once you do this, 1 + True
will actually work. You will also be able to use numeric literals as bools:
*Main> 1 :: Bool
True
*Main> 1 + True
True
This also explains why you get the same error regardless of the order of arguments: the only actual problem in your code is the True
--if that worked, everything else would too.
Upvotes: 4
Reputation: 2918
The error message is saying that the data Bool
is not an instance of the class Num
, if you run in ghci
the following command
Prelude> :info Num
class Num a where
(+) :: a -> a -> a
(*) :: a -> a -> a
(-) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
-- Defined in `GHC.Num'
instance Num Integer -- Defined in `GHC.Num'
instance Num Int -- Defined in `GHC.Num'
instance Num Float -- Defined in `GHC.Float'
instance Num Double -- Defined in `GHC.Float'
You can see that a Num
is a thing that can be added (+)
, multiplied (*)
, substracted (-)
, and so on.
As a Bool
can't behave like this, it doesn't have an instance of Num
. That explains the line in the error No instance for (Num Bool)
since (+)
can only be used on instances of Num
What you are doing in instance Num Bool where (+) a b = True
is saying that now a Bool
behaves also like a Num
, so you have to specify how a Bool
can be added (+)
, multiplied (*)
, etc.
I hope I explained in a simple enough way.
Upvotes: 0
Reputation: 36329
It is the contract of Num that any numeric integer literal can be converted to the desired type.
With your declaration, Haskell tries in reality:
fromIntegral 1 + True
which probably calls your boolean (+) with the first argument undefined. But it doesn't matter, since you never evaluate it.
Try writing it thus:
(+) a b = if a then True else False
and you'll probably see an error.
Upvotes: 1