fundeps => type family

Hi All, Last week I asked a question with the subject "object oriented technique". I got a lot very helpful answers and I thank all who contributed. At the end of my question, I alluded to some problems that I was having with what I wanted to do next, which was to add additional polymorphism. I figured out a solution, which is: ------------------------------------------------- {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} data Rectangle a = MkRectangle { rx, ry, rw, rh :: a } deriving (Eq, Show) drawRect :: Show a => Rectangle a -> String drawRect r = "Rect (" ++ show (rx r) ++ ", " ++ show (ry r) ++ ") -- " ++ show (rw r) ++ " x " ++ show (rh r) data Circle a = MkCircle {cx, cy, cr :: a} deriving (Eq, Show) drawCirc :: Show a => Circle a -> String drawCirc c = "Circ (" ++ show (cx c) ++ ", " ++ show (cy c)++ ") -- " ++ show (cr c) r1 = MkRectangle 0 0 3 2 r2 = MkRectangle 1 1 4 5 c1 = MkCircle 0 0 5 c2 = MkCircle 2 0 7 class ShapeC a s | s -> a where draw :: s -> String copyTo :: s -> a -> a -> s {- -- GADT version data ShapeD a where MkShapeD :: ShapeC a s => s -> ShapeD a -} -- Existential Quantification version data ShapeD a = forall s . ShapeC a s => MkShapeD s instance ShapeC a (ShapeD a) where draw (MkShapeD s) = draw s copyTo (MkShapeD s) x y = MkShapeD (copyTo s x y) mkShape :: ShapeC a s => s -> ShapeD a mkShape s = MkShapeD s instance Show a => ShapeC a (Rectangle a) where draw = drawRect copyTo (MkRectangle _ _ rw rh) x y = MkRectangle x y rw rh instance Show a => ShapeC a (Circle a) where draw = drawCirc copyTo (MkCircle _ _ r) x y = MkCircle x y r r1s = MkShapeD r1 r2s = MkShapeD r2 c1s = MkShapeD c1 c2s = MkShapeD c2 shapes1 = [r1s, r2s, c1s, c2s] drawing1 = map draw shapes1 shapes2 = map mkShape rs ++ map mkShape cs drawing2 = map draw shapes2 -- copy the shapes to the origin then draw them shapes3 = map (\s -> copyTo s 0 0) shapes2 drawing3 = map draw shapes3 ------------------------------------------------- The main difference with my previous version is that the above is polymorphic in the type for the origin and dimensions. (I used a Double previously.) Also, the above version uses existential quantification instead of GADTs, only because some said that that method is more "standard". I had to use functional dependencies in the defintion of class ShapeC to get it to compile and run. Ed Yang's excellent post (http://blog.ezyang.com/2011/03/type-tech-tree) says that type families are equivalent to multiparameter type classes + functional dependencies, so I tried to rewrite the above using type families, but I got stuck. Also the GHC documentaton (http://www.haskell.org/ghc/docs/7.0-latest/html/users_guide/type-families.ht...) says that "Equality constraints ... enable a simple translation of programs using functional dependencies into programs using family synonyms instead. So I tried: class (T s ~ a) => ShapeC a s where type T s :: * draw :: s -> String copyTo :: s -> T s -> T s -> s but got a compile error: Alas, GHC 7.0 still cannot handle equality superclasses: T s ~ a So my question is, how does one convert the above code to use type families instead of functional dependencies? Is one technique preferable over another? Thanks, Tad

On Sun, Apr 3, 2011 at 1:00 PM, Tad Doxsee
"Equality constraints ... enable a simple translation of programs using functional dependencies into programs using family synonyms instead.
So I tried:
class (T s ~ a) => ShapeC a s where type T s :: * draw :: s -> String copyTo :: s -> T s -> T s -> s
but got a compile error:
Alas, GHC 7.0 still cannot handle equality superclasses: T s ~ a
So my question is, how does one convert the above code to use type families instead of functional dependencies? Is one technique preferable over another?
Sadly the documentation assumes the feature that you show is missing. That said, you don't need that feature for the simple FD you have. Just do class ShapeC s where type T s :: * draw :: s -> String copyTo :: s -> T s -> T s -> s This code should work: data ShapeD a = forall s. (ShapeC s, a ~ T s) => MkShapeD s instance ShapeC (ShapeD a) where type T (ShapeD a) = a draw (MkShapeD s) = draw s copyTo (MkShapeD s) x y = MkShapeD (copyTo s x y)

Ryan,
That did it! Thanks a lot for your help.
Tad
On Sun, Apr 3, 2011 at 1:14 PM, Ryan Ingram
On Sun, Apr 3, 2011 at 1:00 PM, Tad Doxsee
wrote: "Equality constraints ... enable a simple translation of programs using functional dependencies into programs using family synonyms instead.
So I tried:
class (T s ~ a) => ShapeC a s where type T s :: * draw :: s -> String copyTo :: s -> T s -> T s -> s
but got a compile error:
Alas, GHC 7.0 still cannot handle equality superclasses: T s ~ a
So my question is, how does one convert the above code to use type families instead of functional dependencies? Is one technique preferable over another?
Sadly the documentation assumes the feature that you show is missing. That said, you don't need that feature for the simple FD you have.
Just do
class ShapeC s where type T s :: * draw :: s -> String copyTo :: s -> T s -> T s -> s
This code should work:
data ShapeD a = forall s. (ShapeC s, a ~ T s) => MkShapeD s
instance ShapeC (ShapeD a) where type T (ShapeD a) = a draw (MkShapeD s) = draw s copyTo (MkShapeD s) x y = MkShapeD (copyTo s x y)
participants (2)
-
Ryan Ingram
-
Tad Doxsee