fundeps for extended Monad definition

Hal Daume III hdaume@ISI.EDU
Wed, 26 Feb 2003 11:00:52 -0800 (PST)


Hi all,

I'm hoping someone can explain some weirdnesses to me.  I want to have a
class that's like the standard Monad class, but is a bit more
general.  That is, I want:

class Monad2 m a ma | m a -> ma, ma -> m a where
  return2 :: a -> ma
  bind2   :: Monad2 m b mb => ma -> (a -> mb) -> mb
  _unused :: m a -> ()
  _unused  = \_  -> ()

Here, all the real work happens in the combined "mb" parameter.  The
_unused definition is just to get Hugs to realize that 'm' should be of
kind * -> * (for GHC, a kind definition does the same thing).

I want to be able to define instances like:

instance Monad2 [] a [a] where
  return2 x = [x]
  bind2 l f = concatMap f l

However, in GHC, if I just give the instance declaration (without the
function definitions), we get:

    Cannot unify the type-signature variable `mb' with the type `[b]'
	Expected type: [b]
	Inferred type: mb
    When using functional dependencies to combine
      Monad2 [] a [a],
	arising from the instance declaration at
/nfs/isd/hdaume/projects/Trials/UsefulDTs/UsefulDTs.hs:114
      Monad2 [] b mb,
	arising from a type signature at
/nfs/isd/hdaume/projects/Trials/UsefulDTs/UsefulDTs.hs:114
    When trying to generalise the type inferred for `bind2'
	Signature type:     forall a mb1 b1.
			    (Monad2 [] b1 mb1) =>
			    [a] -> (a -> mb1) -> mb1
	Type to generalise: forall mb1 b1.
			    (Monad2 [] b1 mb1) =>
			    [a] -> (a -> mb1) -> mb1

This doesn't make sense to me.  Hugs accepts this without
complaint.  Here's why I don't understand it:

We know that m is [].  We have an instance definition (the one we're
defining) that says that for any type x, we have 'Monad2 [] x [x]' where
[] and x determine [x].  This should tell us that mb=[b], but somehow GHC
doesn't get that (or there's something wrong with my reasoning).

When the funciton definitions are provided for the instance, GHC
complains:

/nfs/isd/hdaume/projects/Trials/UsefulDTs/UsefulDTs.hs:119:
    Cannot unify the type-signature variable `mb' with the type `[b]'
	Expected type: a -> [b]
	Inferred type: a -> mb
    In the first argument of `concatMap', namely `f'
    In the definition of `bind2': concatMap f l

and Hugs complains similarly:

*** Expected type : (Monad2 [] a [a], Monad2 [] b c) => [a] -> (a -> c) ->
c
*** Inferred type : (Monad2 [] a [a], Monad2 [] b [c]) => [a] -> (a ->
[c]) -> [c]


Both are saying that they don't know that mb=[b], but I think the fundeps
guarentee this.

Note that if we change the type definition of bind2 to:

  bind2 :: Monad2 m b mb => ma -> (a -> m b) -> m b

then Hugs accepts the instance declaration but GHC complains as it did the
first time.

Can someone explain which is right and why?

Thanks!

 - Hal

--
Hal Daume III

 "Computer science is no more about computers    | hdaume@isi.edu
  than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume