
Yves Pare`s wrote:
I'm working on a library which aims to be a generic interface for 2D rendering. To do that, one of my goals is to enable each implementation of this interface to run in its own monad (most of the time an overlay to IO), thus giving me the following class
class (Monad (IM i x)) => Impl i x where data IM i x :: * -> *
(where IM means Implementation Monad)
I would like to write something like :
class (forall x. Monad (IM i x)) => Impl i where data IM i :: * -> * -> *
It is not clear if the class constraint is really needed. As an aside, a class constraint is perhaps a bit of mis-feature of type classes: it sure improves convenience by making signatures shorter. But it isn't really necessary. Perhaps there are other, better ways of achieving the convenience (the constraint alias proposal comes to mind). If we drop the class constraint, we can move Monad (IM i x) as the constraint on specific methods of the Impl class. The implicit uiniversal quantification on x is well allowed then. For example:
class Impl (i :: * -> *) where data IM i :: * -> * -> * foo :: Monad (IM i x) => Int -> IM i x Int bar :: Monad (IM i x) => IM i x Int -> IM i x Bool cast :: IM i x a -> IM i y a
data Window
instance Impl IO where newtype IM IO x a = IMIO (IO a) foo = IMIO . return bar (IMIO x) = IMIO (fmap (> 42) x) cast (IMIO x) = IMIO x
test :: (Monad (IM i Window), Impl i) => IM i Window Int -> IM i x Bool test = cast . bar
Perhaps this isn't what you had in mind; I more elaborate example would help then.