2011/7/25 Gábor Lehel <illissius@gmail.com>
> type family Frozen t
> type family Thawed t
> class Immutable (Frozen t) => Mutable t where
>   thawedFrozen :: t -> Thawed (Frozen t)
>   unthawedFrozen :: Thawed (Frozen t) -> t
>
> class Mutable (Thawed t) => Immutable t where
>   frozenThawed :: t -> Frozen (Thawed t)
>   unfrozenThawed :: Frozen (Thawed t) -> t
>
> would enable you to explicitly program with the two isomorphisms, while
> avoiding superclass constraints.

Hmm, that's an interesting thought. If I'm guesstimating correctly,
defining instances would be more cumbersome than with the MPTC method,
but using them would be nicer, provided I write helper functions to
hide the use of the isomorphism witnesses. I'll give it a try. Thanks!

I seem to recall that in one of your packages, you had a typeclass
method returning a GADT wrapping the evidence for the equality of two
types, as a workaround for the lack of superclass equality constraints
-- what makes you prefer that workaround in one case and this one in
another?

In a very early version of representable-tries I used my eq package to provide equality witnesses:

http://hackage.haskell.org/packages/archive/eq/0.3.3/doc/html/Data-Eq-Type.html

But I've turned in general to using explicit isomorphisms for things like 

http://hackage.haskell.org/packages/archive/representable-tries/2.0/doc/html/Data-Functor-Representable-Trie.html

because they let me define additional instances that are isomorphic to old instances quickly, while an actual equality witness would require me to bang out a new representation and all 20+ superclass instances. This enables me to write instances for thin newtype wrappers like those in Data.Monoid, etc. that I would be forced to just skip in a heavier encoding.

-Edward