Skip to content

"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
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information