[Haskell-cafe] Rank-2 types in classes
Edward Z. Yang
ezyang at MIT.EDU
Thu Mar 3 01:43:26 CET 2011
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
More information about the Haskell-Cafe
mailing list