"overlapping instances" through FunctionalDependencies
This program prints ("1",2), but if you reverse the order of the two instances, it prints (1,"2").
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
-- extracted from http://lpaste.net/105656
import Control.Applicative
import Data.Functor.Identity
modify :: ((a -> Identity b) -> s -> Identity t) -> (a -> b) -> (s -> t)
modify l f s = runIdentity (l (Identity . f) s)
class Foo s t a b | a b s -> t where
foo :: Applicative f => (a -> f b) -> s -> f t
instance Foo (x, a) (y, a) x y where
foo f (a,b) = (\fa -> (fa,b)) <$> f a
instance Foo (a, x) (a, y) x y where
foo f (a,b) = (\fb -> (a,fb)) <$> f b
main = print $ modify foo (show :: Int -> String) (1 :: Int, 2 :: Int)
Note that the two instances involved Foo (Int, Int) (String, Int) Int String and Foo (Int, Int) (Int, String) Int String are not actually overlapping. But, they have the same a, b, and s fields and it seems that this makes GHC think that either one is equally valid, thanks to the fundep.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 7.8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |