TypeFamilies vs. FunctionalDependencies & type-level recursion
oleg at okmij.org
oleg at okmij.org
Tue Jun 21 09:35:46 CEST 2011
I have implemented type-level TYPEREP (along with a small library for
higher-order functional programming at the type level). Overlapping
instances may indeed be avoided. The library does not use functional
David Mazi`eres suggested a good test
> A good test would be whether superclasses let
> you eliminate N^2 mtl instances and do something equivalent to:
> instance (Monad m) => MonadState s (StateT s m) where
> get = StateT $ \s -> return (s, s)
> put s = StateT $ \_ -> return ((), s)
> instance (Monad (t m), MonadTrans t, MonadState s m) =>
> MonadState s (t m) where
> get = lift get
> put = lift . put
Exactly this code is implemented in Example.hs. Here's an excerpt:
> -- Default instance
> instance (Monad (t m), MonadState m, MonadTrans t)
> => MonadState' (t m) HFalse where
> type MState' (t m) HFalse = MState m
> get' _ = trace "Default get" $ lift get
> put' _ = lift . put
> -- Special instances
> instance (Monad m)
> => MonadState' (StateT s m) HTrue where
> type MState' (StateT s m) HTrue = s
> get' _ = trace "Special get" . StateT $ \s -> return (s, s)
> put' _ s = StateT $ \_ -> return ((), s)
> -- add more special instances if needed ...
plus one more general dispatching instance. Because of the additional
flag, HTrue vs HFalse, the above instances do not overlap.
> The key piece of magic I need here (and in so many other places) is to
> be able to do one thing at the type level if x is a particular type
> (e.g., NoSelector) or sometimes one of a small number of types, and to
> do something else if x is any other type.
TTypeable.hs does exactly that.
> You'd need to be able to do things like:
> -- Type-level if-then-else
> closed type family IfEq :: * -> * -> * -> * -> *
> type instance IfEq a b c d = d
> type instance IfEq a a c d = c
The code does that.
> I also can't quite figure out how to pass around ad-hoc polymorphic
> functions the way you can with proxy types and a class such as:
> class Function f a b | f a -> b where funcall :: f -> a -> b
And that too.
Although the code is usable already, a bit of sugaring from GHC would
greatly help. At the very least, automatic deriving of TYPEOF. A
longer wish is for a a built-in equality comparison on TyCon_name.
Perhaps we might wish to begin to consider if overlapping
instances could be deprecated?
More information about the Haskell-prime