Are associated types synonyms like type classes?

I read the easy parts of the "Associated Types with Class" and "Associated Type Synonyms" papers. An associated type synonym seems to kind of work similarly to a restricted form of class. In what way are the two following examples different? -- define a class with a type synonym, and a set of operations class A a where type B b foo :: a -> B b instance A Int where type B = Bool foo = (==0) -- define two classes, and an function that . class A a, B b where foo :: a -> b instance A Int, B Bool where foo = (==0) Also, has anybody written a paper on the differences between typeclasses + associated types and ML's module system + overloading? Thanks, Brian

Hello Brian, Friday, September 1, 2006, 8:32:55 PM, you wrote:
I read the easy parts of the "Associated Types with Class" and "Associated Type Synonyms" papers. An associated type synonym seems to kind of work similarly to a restricted form of class. In what way are the two following examples different?
-- define a class with a type synonym, and a set of operations class A a where type B b foo :: a -> B b
instance A Int where type B = Bool foo = (==0)
-- define two classes, and an function that . class A a, B b where foo :: a -> b
instance A Int, B Bool where foo = (==0)
where you've find such unusual syntax? :) GHC/Hugs supports multi-parameter type classes (MPTC): class AB a b where foo :: a -> b instance AB Int Bool where foo = (==0) AT replaces MPTC with FD (functional dependency), which allows to specify which type parameter of MPTC is detremined by another one, i.e.: class AB a b | a->b where .... for further details about MPTC+FD see chapter 7.1.1 in the http://cvs.haskell.org/Hugs/pages/hugsman/exts.html
Also, has anybody written a paper on the differences between typeclasses + associated types and ML's module system + overloading?
"ML Modules and Haskell Type Classes: A Constructive Comparison" http://www.informatik.uni-freiburg.de/~wehr/diplom/Wehr_ML_modules_and_Haske... -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Bulat, Stefan,
My question wasn't clear. I understand already that classes with associated
types are are alternative to MPTC with fundeps.
When using AT then we have to decide what part of the abstraction is the
class and what part is the associated type. Sometimes this seams arbitrary.
If we have:
class A a where
type B b
f :: a -> B b
instance A Int where
type B = Bool
f = (==0)
Can't we also rewrite it as:
class B b where
type A a
f :: A a -> b
instance B Bool where
type A = Int
f = (==0)
What is the practical difference between class A and class B? With class A
we can define instances so that f is overloaded (Int -> Bool), (String ->
Bool), (Bool -> Bool) by defining instances of A for Int, String, and Bool,
but we cannot overload it more (Int -> String), (Int -> Int) because we can
only have on "instance A Int". The converse is true for class B. Is that the
only difference?
If so, then why do we have "associated types" instance of "associated
classes" like this?:
class A a where
class B b where
f :: a -> b
instance A Int where
instance B Bool where
f = (==0)
The made-up syntax I presented in my previous message was just a different
way of writing the above (which is also made-up syntax):
class A a, B b where f :: a -> b
instance A Int, B Bool where f = (==0)
class Elem elem, Collect collect where
empty :: collect
insert :: elem -> collect -> collect
toList :: collect -> [elem]
Thanks for your help,
Brian
On 9/1/06, Bulat Ziganshin
Hello Brian,
Friday, September 1, 2006, 8:32:55 PM, you wrote:
I read the easy parts of the "Associated Types with Class" and "Associated Type Synonyms" papers. An associated type synonym seems to kind of work similarly to a restricted form of class. In what way are the two following examples different?
-- define a class with a type synonym, and a set of operations class A a where type B b foo :: a -> B b
instance A Int where type B = Bool foo = (==0)
-- define two classes, and an function that . class A a, B b where foo :: a -> b
instance A Int, B Bool where foo = (==0)
where you've find such unusual syntax? :) GHC/Hugs supports multi-parameter type classes (MPTC):
class AB a b where foo :: a -> b
instance AB Int Bool where foo = (==0)
AT replaces MPTC with FD (functional dependency), which allows to specify which type parameter of MPTC is detremined by another one, i.e.:
class AB a b | a->b where ....
for further details about MPTC+FD see chapter 7.1.1 in the http://cvs.haskell.org/Hugs/pages/hugsman/exts.html
Also, has anybody written a paper on the differences between typeclasses + associated types and ML's module system + overloading?
"ML Modules and Haskell Type Classes: A Constructive Comparison"
http://www.informatik.uni-freiburg.de/~wehr/diplom/Wehr_ML_modules_and_Haske...
-- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Hello Brian, Saturday, September 2, 2006, 10:19:17 PM, you wrote:
What is the practical difference between class A and class B? With class A we can define instances so that f is overloaded (Int -> Bool), (String -> Bool), (Bool -> Bool) by defining instances of A for Int, String, and Bool, but we cannot overload it more (Int -> String), (Int -> Int) because we can only have on "instance A Int". The converse is true for class B. Is that the only difference?
If so, then why do we have "associated types" instance of "associated classes" like this?: class A a where class B b where f :: a -> b
instance A Int where instance B Bool where f = (==0)
class defines a set of types, type defines just one type. So, defining class inside class or using your hand-made syntax we will got just the same thing as MPTC:
The made-up syntax I presented in my previous message was just a different way of writing the above (which is also made-up syntax):
class A a, B b where f :: a -> b instance A Int, B Bool where f = (==0)
using associated type inside class is a way to define many-to-one relationship, i.e. it's the same as MPTC+FD
class Elem elem, Collect collect where empty :: collect insert :: elem -> collect -> collect toList :: collect -> [elem]
your syntax differs from MPTC only in that we have two class names - Elem and Collect, but that is not that we need - we need type restrictions that joins collection with its element types: insertMany :: (Collection c e) => [e] -> c -> c if we will try to use different class names here, the requirement to insert into collection elements it can hold, will not be expressed: insertMany :: (Elem e, Collect c) => [e] -> c -> c -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Brian Smith:
When using AT then we have to decide what part of the abstraction is the class and what part is the associated type. Sometimes this seams arbitrary. If we have:
class A a where type B b f :: a -> B b instance A Int where type B = Bool f = (==0)
Can't we also rewrite it as:
class B b where type A a f :: A a -> b instance B Bool where type A = Int f = (==0)
If it is arbitrary, you should use a two parameter class. The bias in an associated type is on purpose; ie, an associated type should be used if one type depends on the other. Bulat wrote:
Also, has anybody written a paper on the differences between typeclasses + associated types and ML's module system + overloading?
"ML Modules and Haskell Type Classes: A Constructive Comparison" http://www.informatik.uni-freiburg.de/~wehr/diplom/Wehr_ML_modules_and_Haske...
In addition to this comparison, there is now also a proposal for type classes with associated types as a mode of use of ML modules. See our forthcoming POPL paper: http://www.cse.unsw.edu.au/~chak/papers/DHC07.html Ie, this gives you ML modules + overloading. Manuel

Brian,
I read the easy parts of the "Associated Types with Class" and "Associated Type Synonyms" papers. An associated type synonym seems to kind of work similarly to a restricted form of class. In what way are the two following examples different?
-- define a class with a type synonym, and a set of operations class A a where type B b foo :: a -> B b
instance A Int where type B = Bool foo = (==0)
-- define two classes, and an function that . class A a, B b where foo :: a -> b
instance A Int, B Bool where foo = (==0)
It is more like -- using multi-parameter type classed with functional dependencies (as found, for example, in GHC): class A a b | a -> b where foo :: a -> b instance A Int Bool where foo = (== 0) Cheers, Stefan
participants (4)
-
Brian Smith
-
Bulat Ziganshin
-
Manuel M T Chakravarty
-
Stefan Holdermans