Class constraints for associated type synonyms
brandon_m_moore at yahoo.com
Thu Mar 24 04:22:00 CET 2011
> From: Jan-Willem Maessen <jmaessen at alum.mit.edu>
> Sent: Wed, March 23, 2011 8:43:14 PM
> Hi all -
> I've been trying to construct a class declaration with an associated
> type synonym, but I'd like to constrain that type to belong to a
> particular class.
> Consider the following class:
> class Monoid m => Constructs c m | c -> m where
> construct :: m -> c
> This captures the idea that the collection c ought to be constructed
> using the monoid m (say if we're doing the construction using the
> Writer monad)--the functional dependency indicates the desire for the
> type c to injectively determine the choice of monoid m. For example:
> newtype ListBuilder a = Builder ([a] -> [a]) deriving (Monoid)
> instance Constructs [a] (ListBuilder a) where
> construct (Builder f) = f 
> instance (Ord a) => Constructs (Set a) (Set a) where
> construct = id
> Now I'd like to be able to do the same thing using an associated type
> synonym, something like this:
> type GeneratorOf a :: * -> *
> construct :: GeneratorOf a -> a
> Now, it seems I need FlexibleInstances to do this when I'm using an
> associated type synonym, but I don't need the flexibility when using a
> multiparameter type class.
The conditions in the report are quite restrictive - in particular, the context
must consist only of classes applied to type variables. When you used a
multiparameter type class and an FD, the type you wanted to mention was
just a type variable.
The GHC user's guide suggests FlexibleContexts should be enough to allow
you to declare that class:
FlexibleInstances seems only to affect what is allowed in an instance head.
I don't see how it helps at all, unless it implies some other extensions.
You might still run into termination issues - as a an associated type synonym
rather than an associated data type, GeneratorOf a might very well be something
large, and the conditions (disabled by UndecidableInstances) don't take
of the acyclic superclass relationship.
> In both cases the instance constraint
> involves types that can be injectively inferred (if I have my
> terminology straight; work with me here) from a single type mentioned
> in the class head. In particular, I can imagine storing the
> dictionary for Monoid (GeneratorOf a) in the dictionary for Generable
> a, and thus allowing context reduction of (Monoid (GeneratorOf tyvar))
> to (Generable tyvar). Meanwhile, I think there are things that are
> permitted by FlexibleInstances that I'd rather *not* have creeping
> into my programs.
Do you have any examples? I've always found FlexibleInstances alone
unproblematic - it's only when you add OverlappingInstances or worse
that things can get messy.
More information about the Glasgow-haskell-users