fundeps for extended Monad definition

oleg@pobox.com oleg@pobox.com
Thu, 27 Feb 2003 19:15:33 -0800 (PST)


Hello!

Simon Peyton-Jones wrote:

> class C a b | a -> b where {}

> instance C Int Int where {}

> f1 :: (forall b. (C Int b) => Int -> b)
> f1 x = undefined

Indeed, this gives an error message 
    Cannot unify the type-signature variable `b' with the type `Int'
        Expected type: Int
        Inferred type: b

The reason, which is thoroughly explained in Simon Peyton-Jones'
message, is that the given type signature is wrong: it should read
	f1 :: (exists b. (C Int b) => Int -> b)

Alas, 'exists' is not an allowed type quantifier. Not explicitly that
is. We can get 'exists' if we use the permitted 'forall' in a negative
position (aka in an existential type).

The following code

> class C a b | a -> b where {}

> instance C Int Int where {}

> newtype M a = M (forall b.(C a b) => b)
> f :: Int -> M Int
> f x = M undefined

typechecks in both Haskell compilers.

Hal Daume's original example works as well:

> newtype MM2 m a = MM2 (forall mb.(Monad2 m a mb) => mb)
       

> class Monad2 m a ma | m a -> ma, ma -> m a where
>   return2 :: a -> ma
>   bind2   :: ma -> (a -> (MM2 m a)) -> (MM2 m a)
>   unused :: m a -> ()
>   unused  = \_  -> ()

> instance Monad2 [] a [a] where
>        bind2 = error "urk"

Again, it typechecks both in Hugs and GHC.