On Fri, Apr 10, 2009 at 11:15 AM, Yusaku Hashimoto <[email protected]> wrote:
> 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
_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to