I have a bit of code that would be more cleanly written if I could treat Monad
s as Num
s (where applicable, of course). Easily enough done:
{-# LANGUAGE FlexibleInstances #-}
import Control.Monad (liftM, liftM2)
import Data.Char (digitToInt)
instance (Monad m, Num a) => Num (m a) where
(+) = liftM2 (+)
(-) = liftM2 (-)
(*) = liftM2 (*)
abs = liftM abs
signum = liftM signum
fromInteger = return . fromInteger
square :: (Monad m, Num a) => m a -> m a
square x = x * x
-- Prints "Just 9", as expected
main = putStrLn $ show $ square $ Just 3
But when I add the following function to the file …
digitToNum :: (Num a) => Char -> a
digitToNum = fromIntegral . digitToInt
… I receive the following error:
monadNumTest.hs:15:14:
Overlapping instances for Num (m a)
arising from a use of `*'
Matching instances:
instance (Monad m, Num a) => Num (m a)
-- Defined at monadNumTest.hs:6:10
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
(The choice depends on the instantiation of `m, a'
To pick the first instance above, use -XIncoherentInstances
when compiling the other instance declarations)
In the expression: x * x
In an equation for `square': square x = x * x
This doesn't make sense to me, because (1) digitToNum
is never called and (2) Ratio
isn't a Monad
. So I'm unsure how or why that's a problem. Any tips around this would be appreciated.
This is GHC 7.4.2, using the Haskell Platform 2012.4.0.0.