I was thinking about the design of superclass default instances. I think that we can get relatively far using the following extensions together:
1) Multiple instance declarations instance (Functor[a], Monad [a]) where fmap = map (>>=) = flip concatMap return = (:[]) -- Declaration above is syntactic sugar for 2 declarations: -- instance Functor[a] -- where -- fmap = map -- instance Monad [a] -- where -- (>>=) = flip concatMap -- return = (:[]) 2) Context synonyms -- (MonadAndFunctor a) is synonym for (Functor a, Monad a) context (Functor a, Monad a) => MonadAndFunctor a -- Using synonims with multiple class declarations we can define instances like instance MonadAndFunctor [a] where fmap = map (>>=) = flip concatMap return = (:[]) -- Declaration above is syntactic sugar for -- instance (Functor[a], Monad [a]) -- where -- fmap = map -- (>>=) = flip concatMap -- return = (:[]) 3) And finally Default superclass instances Class contains default instances for superclasses: class Functor m => Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a -- default superclass instance: instance Functor m where fmap f m = m >>= (return . f) Default superclass implementations are used only when multiple instance declarations are used: -- no default superclass instance is used. Error is emitted when there is no Functor instance instance Monad [a] where ... -- default superclass instance is used: instance Functor [a], Monad [a] where (>>=) = ... return = ... -- functor instance is generated automatically -- fmap = ... Suppose that we make Functor to be Monad's superclass. Combination of this three extensions allows us to define compatibility modules: module Control.Monad.Compat (Monad) where import qualified Control.Monad (Monad(..), Functor(..)) as CM context CM.Functor m, CM.Monad m => Monad m When we have compilation failure in client code after our Monad definition change: "No Functor instance found for Foo": instance Monad Foo where ... , we simply add following two lines to the module: import Prelude hiding (Monad) import Control.Monad.Compat (Monad) and compilation succeeds. Pros: Client code can remain Haskell 98/2010 and doesn't require any extensions. Three extensions seems simple when separate (I think there are many corner cases) Cons: Intervention is required into client code (But I think it is required anyway). -- Victor Nazarov _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users