
On Fri, Apr 10, 2009 at 11:15 AM, Yusaku Hashimoto
Hi, I changed a line, It type checks. But I can't explain why your version does not type check.
Thanks, I can't explain it either because I don't completely understand functional dependencies. So I rewrote it using type families which I find much easier to understand: ---------------------------------------- {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-} module Iso where class Iso m where type Inner m :: * -> * close :: forall a. Inner m a -> m a open :: forall a. m a -> Inner m a deriveReturn :: (Monad (Inner m), Iso m) => a -> m a deriveReturn = close . return deriveBind :: (Monad (Inner m), Iso m) => m a -> (a -> m b) -> m b deriveBind m k = close $ open m >>= open . k ---------------------------------------- newtype T1 m a = T1 { unT1 :: A1 m a } type A1 m a = m a instance Iso (T1 m) where type Inner (T1 m) = m close = T1 open = unT1 instance Monad m => Monad (T1 m) where return = deriveReturn (>>=) = deriveBind ---------------------------------------- You can also get a Monad instance "for free" if you aren't afraid of UndecidableInstances: ---------------------------------------- {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} instance (Monad (Inner m), Iso m) => Monad m where return = deriveReturn (>>=) = deriveBind ---------------------------------------- This seems useful. Does this exists somewhere on hackage? regards, Bas