
On Friday 17 September 2010 4:04:26 pm Gábor Lehel wrote:
What I would *want* to write is this:
class (Mutable (Thawed a), Frozen (Thawed a) ~ a) => Immutable a where type Thawed a :: * thaw :: a -> Thawed a
class (Immutable (Frozen a), Thawed (Frozen a) ~ a) => Mutable a where type Frozen a :: * freeze :: a -> Frozen a
This looks considerably nicer, but it's not valid -- I get a cycle in class declarations via superclasses error, on the one hand, and (if I remove that) an infinite loop in the typechecker (context reduction stack overflow) on the other (FlexibleContexts being a prerequisite for most of the interesting things you can do with TypeFamilies).
So what should one, theoretically, do here? Is there a way to express this using TypeFamilies which preserves both the semantics and the symmetry of the FDs version, and is also valid? Or should one just go ahead and use the FDs because, in this case, they're simply better suited? *Or* should one just suck it up and go with the ugly TypeFamilies version because TypeFamilies are The Future*?
What about: class (Thawed frozen ~ thawed, Frozen thawed ~ frozen) => TwoPhase thawed frozen where type Thawed frozen :: * type Frozen thawed :: * thaw :: frozen -> thawed freeze :: thawed -> frozen This is the translation I'd expect for the fundep. And ideally, in the future, you could use the original class with fundeps as sugar for the above, because fundeps are a nice way of expressing mutual dependency like this (just as associated types are nicer than making the associated type a class parameter as is required by fundeps). -- Dan