TypeFamilies vs. FunctionalDependencies & type-level recursion

dm-list-haskell-prime at scs.stanford.edu dm-list-haskell-prime at scs.stanford.edu
Mon Jun 20 19:28:37 CEST 2011

At Mon, 20 Jun 2011 09:57:38 +0200,
José Pedro Magalhães wrote:
>      class JSON1 a r | a -> r
>         toJSON1 :: a -> r
>      instance (JSON a) => JSON1 (S1 NoSelector (K1 c a)) [Value] where
>         toJSON1 (M1 (K1 a)) = [toJSON a]
>      instance (Selector x, JSON a) => JSON1 (S1 x (K1 c a)) [(String, Value)]
>     where
>         toJSON1 s@(M1 (K1 a)) = [(nameOf s undefined, toJSON a)]
>         where nameOf :: S1 c f p -> c -> String
>               nameOf _ c -> selName c
>     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.
> Right. I think this is often essential.

One thing you could do to help in this specific case would be to use a
different M1 tag--e.g., M1 S ... for selectors and M1 NS ... for
fields without selectors (or K1 NS).  I presume you've already
considered this and/or it's too late to make such a change.  (Or to
move the distinction up to the constructor with two different
constructor tags, CR and CN for record and no-record.)

Anyway, as you mention, there are other situations where you still
need Overlapping/UndecidableInstances.


More information about the Haskell-prime mailing list