
On Fri, Sep 17, 2010 at 10:19 PM, Dan Doel
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).
Hmm. I had a similar thought, but dismissed it because I was under the impression that you needed to use all the parameters of the class as parameters of its associated types. But apparently that was mistaken -- or, at least, your example compiles. :) The redundancy is sort of annoying ('thawed' and 'Thawed frozen' both being necessary and necessarily equivalent). This is a case where associated type defaults would be helpful, to eliminate at least some of it (namely, having to define Thawed and Frozen in every instance, even though only one definition is possible). Anyway, it's a shame you can't really decouple the two halves as in my nonworking example, but this is nicer than the other alternative I had. Thanks!
-- Dan _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Work is punishment for failing to procrastinate effectively.