Monad
s を s として扱うことができれば、よりきれいに記述できるコードが少しありますNum
(もちろん、該当する場合)。簡単に完了:
{-# 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
しかし、次の関数をファイルに追加すると…
digitToNum :: (Num a) => Char -> a
digitToNum = fromIntegral . digitToInt
… 次のエラーが表示されます。
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
(1)digitToNum
は決して呼び出されず、(2)Ratio
ではないため、これは私には意味がありませんMonad
。したがって、それがどのように、またはなぜ問題なのかはわかりません。これに関するヒントをいただければ幸いです。
これは、Haskell Platform 2012.4.0.0 を使用する GHC 7.4.2 です。