Re: [Haskell-cafe] Rank-2 types in classes

2011-03-03 Thread Yves Parès
Thanks for your proposal.

> It is not clear if the class constraint is really needed.

Well 'IM' means 'ImplementationMonad', so it wouldn't make much sense if an
IM of an implementation wasn't also a monad. And since IM is the central
monad of the library, a lot of functions will use IM.
The methods will be spreaded over various classes. For instance the class
IWindow :

class IWindow i where
withinWindow :: Window -> IM i Window a -> IM i x a

So a method like 'cast' shouldn't exist, since it would allow the user to
switch the context freely. Methods like withinWindow will do that, but
safely.

2011/3/3 

>
> 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.
>
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Rank-2 types in classes

2011-03-03 Thread oleg

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.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Rank-2 types in classes

2011-03-02 Thread Edward Z. Yang
The trick is to write the rank-2 type in the function that runs
the monad, and leave the typeclasses skolemized.

Here's an example:

-- | Typeclass for monads that write or read to a network.  Useful
-- if you define operations that need to work for all such monads.
-- You're expected to put extra constraints on h.
class (Network g, Monad (m g n), Applicative (m g n), Functor (m g n)) => 
NetworkMonad m g n where
-- | Unsafely converts an 'IO' operation that takes an 'AIG' as an
-- argument into an operation in some 'NetworkMonad'.
unsafeIOToNetwork :: (GEnv g -> IO a) -> m g n a
...

class OpaqueNetwork g => Network g where
-- * We cannot put NetworkMonad constraint on GNT g and GNQ g because we
--   need to be able to put that constraint as a rank-2 monad.
-- * This has a lot of "stuff" in it, maybe we'll split it up later.
data GNode g  :: *  -- ^ phantom type
  -> *  -- ^ data type
data GNT g:: *  -- ^ phantom type
  -> * -> * -- ^ monad
data GNQ g:: *  -- ^ phantom type
  -> * -> * -- ^ monad
data GEnv g   :: *

one:: GNode g n
zero   :: GNode g n

runNT  :: (forall n. NetworkMonad GNT g n => GNT g n ()) -> g
withNT :: g -> (forall n. NetworkMonad GNT g n => GNT g n ()) -> g

There are numerous other problems with this route (can you see them from
the sample code?) but I found this solution to be mostly acceptable.

Cheers,
Edward

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Rank-2 types in classes

2011-03-02 Thread Max Bolingbroke
2011/3/2 Yves Parès :
> Is what I'm trying to do a common technique to type-ensure contexts or are
> there simpler methods?

I don't understand your problem well enough to be able to venture a
solid opinion on this. Sorry! What you have detailed so far doesn't
sound too complex, though.

Max

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Rank-2 types in classes

2011-03-02 Thread Yves Parès
Thank you !

Is what I'm trying to do a common technique to type-ensure contexts or are
there simpler methods?


2011/3/2 Max Bolingbroke 

> On 2 March 2011 09:11, Yves Parès  wrote:
> > class (forall x. Monad (IM i x)) => Impl i where
> > data IM i :: * -> * -> *
> >
> > But GHC forbids me to do so.
>
> The way I usually work around this is by doing something like the
> following pattern:
>
> {{{
> class Monad1 m where
>return1 :: a -> m x a
>bind1 :: m x a -> (a -> m x b) -> m x b
>
> instance Monad1 (IM MyI) where
>return1 = ...
>bind1 = ...
>
> instance Monad1 m => Monad (m x) where
>return = return1
>(>>=) = bind1
> }}}
>
> Your class can now have a (Monad1 (IM i)) superclass context. You will
> have to enable a few extensions to get this through - most likely
> FlexibleInstances and OverlappingInstances.
>
> Cheers,
> Max
>
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Rank-2 types in classes

2011-03-02 Thread Max Bolingbroke
On 2 March 2011 09:11, Yves Parès  wrote:
> class (forall x. Monad (IM i x)) => Impl i where
>     data IM i :: * -> * -> *
>
> But GHC forbids me to do so.

The way I usually work around this is by doing something like the
following pattern:

{{{
class Monad1 m where
return1 :: a -> m x a
bind1 :: m x a -> (a -> m x b) -> m x b

instance Monad1 (IM MyI) where
return1 = ...
bind1 = ...

instance Monad1 m => Monad (m x) where
return = return1
(>>=) = bind1
}}}

Your class can now have a (Monad1 (IM i)) superclass context. You will
have to enable a few extensions to get this through - most likely
FlexibleInstances and OverlappingInstances.

Cheers,
Max

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Rank-2 types in classes

2011-03-02 Thread Yves Parès
Hello,

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)

Here, 'x' aims at being a phantom type that ensures a type safe context for
some operations.
E.g., operations that need to occur in a window will have the type:
   IM i Window a
And will be run by the function:
   withinWindow :: Window -> IM i Window a -> IM i x a

This makes an operation that doesn't instantiate 'x' context-independent.

My problem, then, is that in the definition of class Impl the type variable
'x' is useless, since every implementation must leave uninstantiated.

I would like to write something like :

class (forall x. Monad (IM i x)) => Impl i where
data IM i :: * -> * -> *

But GHC forbids me to do so.

Any suggestion would be warmly welcomed.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe