Hello! It seems we can truly implement Monad2 without pushing the envelope too far. The solution and a few tests are given below. In contrast to the previous approach, here we lift the type variables rather than bury them. The principle is to bring the type logic programming at the level of classes and instances but avoid putting them at the level of their members.
class TwoMonadific m a ma | m a -> ma, ma -> m a where unused :: m a -> () unused = undefined
instance TwoMonadific [] a [a]
instance TwoMonadific Maybe a (Maybe a)
class (TwoMonadific m a ma, TwoMonadific m b mb) => Monad2 m a b ma mb where return2 :: a -> ma bind2 :: ma -> (a -> mb) -> mb
instance Monad2 [] a b [a] [b] where return2 x = [x] bind2 l f = concatMap f l
instance Monad2 Maybe a b (Maybe a) (Maybe b) where return2 x = Just x bind2 Nothing f = Nothing bind2 (Just x) f = f x
test1 = (return2 5) `bind2` (\n -> [1..n]) `bind2` (\n -> [1..n])
test2 = (return2 5) `bind2` Just `bind2` Just
*Main> test1 [1,1,2,1,2,3,1,2,3,4,1,2,3,4,5] *Main> test2 Just 5
It all works in GHC. Hugs complaints about return2: ERROR "/tmp/b.hs":11 - Ambiguous type signature in class declaration *** ambiguous type : Monad2 a b c d e => b -> d *** assigned to : return2 My version of Hugs isn't up-to-date though.