ghc derives different type signature for equal functions with overlapping instances
Insert "This flag does not change ghc's behaviour when no verlapping instances are present." after "The -fallow-overlapping-instances lag instructs GHC to allow more than one instance to match, provided here is a most specific one." in http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#instance-overlap
(old description follows for reference)
The code below derives two different type signatures for the same function in two different modules.
One of these modules defines a new instance for the Monad
class. What's interesting is that this causes the type checker to derive a more general type than before. I think that's a bug.
Another interesting point is that the code below works without -fallow-overlapping-instances,
but if the instances from A.hs
and from B.hs
are combined in a single file, the compiler complains very loudly. The derived types are unaffected by -fallow-overlapping-instances
.
==> A.hs <==
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
module A (MaybeT (..), module Control.Monad) where
import Control.Monad
newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}
instance Monad m => Monad (MaybeT m)
==> B.hs <==
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
module B (qqq) where
import A
data Foo a = Foo
instance Monad (MaybeT Foo) where
qqq _ = runMaybeT (runMaybeT (return 1) >> return 2)
==> C.hs <==
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
module C (rrr) where
import A
rrr _ = runMaybeT (runMaybeT (return 1) >> return 2)
==> D.hs <==
module D (qqq, rrr) where
import B
import C
{-
# ghci -fallow-overlapping-instances D.hs
GHCi, version 6.7.20070716: http://www.haskell.org/ghc/ :? for help
(...)
Ok, modules loaded: C, D, A, B.
*D> :t qqq
qqq :: (Monad (A.MaybeT m), Num t1) => t -> m (Maybe t1)
*D> :t rrr
rrr :: (Monad m, Num t1) => t -> m (Maybe t1)
*D> :i MaybeT
newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}
-- Defined at A.hs:6:8-13
instance [overlap ok] (Monad m) => Monad (MaybeT m)
-- Defined at A.hs:8:0-35
-}
I think that the type derived for qqq
is correct in the presence of overlapping instances.