Skip to content

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.

Edited by Bertram Felgenhauer
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information