
Hi, I often have a situation where I'm designing specialized components to do a more general task. Examples could include mail folder code (maildir, mbox, etc), configuration file parsing, protocol handlers for URL accesses, logging backends, etc. For some of these, I've used a data object with named fields, each one of them being a function that performs various tasks (open connection to the URL, read data, whatever.) So, I get a standard interface. The advantage of this approach is that I can build a list containing all sorts of different data objects in it. For others, I've used typeclasses, and made the different specialized components a member of the typeclass. This seems to provide a cleaner interface, and one that is more readily extended (maybe I want to support IMAP folders, and support all its searching capabilities too). On the other hand, it's difficult or impossible to make a list of a bunch of different types of things that have nothing in common save being members of the class. Is there any advice on the best way to do these things? Thanks, John

Major apologies for this repeated plug for HList. Anyway, HLists [1] are *exactly* designed for this sort of problem. Well, one can also use existential quantification + bounded polymorphism; with the shapes benchmark providing a good example [2]. The trade-offs are explored a little bit on the OOHaskell slides and in the corresponding code base [3]. Cheers, Ralf [1] http://homepages.cwi.nl/~ralf/HList/ [2] http://www.angelfire.com/tx4/cus/shapes/haskell.html [3] http://homepages.cwi.nl/~ralf/OOHaskell/ John Goerzen wrote:
Hi,
I often have a situation where I'm designing specialized components to do a more general task. Examples could include mail folder code (maildir, mbox, etc), configuration file parsing, protocol handlers for URL accesses, logging backends, etc.
For some of these, I've used a data object with named fields, each one of them being a function that performs various tasks (open connection to the URL, read data, whatever.) So, I get a standard interface. The advantage of this approach is that I can build a list containing all sorts of different data objects in it.
For others, I've used typeclasses, and made the different specialized components a member of the typeclass. This seems to provide a cleaner interface, and one that is more readily extended (maybe I want to support IMAP folders, and support all its searching capabilities too).
On the other hand, it's difficult or impossible to make a list of a bunch of different types of things that have nothing in common save being members of the class.
Is there any advice on the best way to do these things?
Thanks,
John
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On the other hand, it's difficult or impossible to make a list of a bunch of different types of things that have nothing in common save being members of the class.
I've recently been playing with making, for each class C, a "interface" datatype IC (appropriately universally and existentially qualified so as to include a dictionary for class C), and then making this IC an instance of class C. Then I can wrap any instance of C up in an IC, and make a list of those. The casts get a bit annoying, though; the compiler can't figure out that this IC is in some sense the maximum type in class C, and so can't resolve things like f :: MyClass a => [a] -> b f = ... upcast :: MyClass a => a -> IMyClass -- usually defined as an instance of class Cast upcast x = IMyClass x f [upcast a, upcast b] -- yields type error Instead, you have to redefine f as follows: f' :: [IMyClass] -> b which is a bit annoying. HTH. --KW 8-)

On Tue, 14 Dec 2004 15:40:13 +0000, Keith Wansbrough
On the other hand, it's difficult or impossible to make a list of a bunch of different types of things that have nothing in common save being members of the class.
I've recently been playing with making, for each class C, a "interface" datatype IC (appropriately universally and existentially qualified so as to include a dictionary for class C), and then making this IC an instance of class C. Then I can wrap any instance of C up in an IC, and make a list of those.
I think there should be standard syntax for this...
Some sort of operator for turning one or several type classes into an
interface datatype.
So you could write something like something like...
f ::

There are two ways to do the list of class members, existentials is one way... data MyBox = forall a . MyClass a => MyBox a type MyClassList = [MyBox] f :: MyClassList -> MyClassList An alternative is to use a heterogeneous list (see the HList library): http://www.cwi.nl/~ralf/HList This allows heterogeneous lists with static typing, which can be constrained by a class as follows: class MyClassList x instance MyClassList HNil instance (MyClassList l,MyClass v) => MyClassList (HCons v l) The constraint "MyClassList" now implies a heterogeneous list of members of "MyClass": f :: (MyClassList l,MyClassList l') => l -> l' This represents a filter function on a heterogeneous list of class members - The drawback is that the list must be statically typecheckable... If you require run-time list construction from IO actions, then you want to use existentials. Keean Sebastian Sylvan wrote:
On Tue, 14 Dec 2004 15:40:13 +0000, Keith Wansbrough
wrote: On the other hand, it's difficult or impossible to make a list of a bunch of different types of things that have nothing in common save being members of the class.
I've recently been playing with making, for each class C, a "interface" datatype IC (appropriately universally and existentially qualified so as to include a dictionary for class C), and then making this IC an instance of class C. Then I can wrap any instance of C up in an IC, and make a list of those.
I think there should be standard syntax for this... Some sort of operator for turning one or several type classes into an interface datatype.
So you could write something like something like...
f ::
-> [ ] -> f a xs = ... So the first parameter is just a value of the interface datatype data ShowNum = forall a . (Show a, Num a) => ShowNum a
And it's all automatically up and downcasted.
This is one of the more powerful idioms in languages such as Java (collections of objects which satisfy some interface, for instance) and should, IMO, be supported by some special syntax to facilitate it's use in Haskell.
/S

See the HList library (http://www.cwi.ni/~ralf/HList) and use an HList constrained by your interface. Keean. John Goerzen wrote:
Hi,
I often have a situation where I'm designing specialized components to do a more general task. Examples could include mail folder code (maildir, mbox, etc), configuration file parsing, protocol handlers for URL accesses, logging backends, etc.
For some of these, I've used a data object with named fields, each one of them being a function that performs various tasks (open connection to the URL, read data, whatever.) So, I get a standard interface. The advantage of this approach is that I can build a list containing all sorts of different data objects in it.
For others, I've used typeclasses, and made the different specialized components a member of the typeclass. This seems to provide a cleaner interface, and one that is more readily extended (maybe I want to support IMAP folders, and support all its searching capabilities too).
On the other hand, it's difficult or impossible to make a list of a bunch of different types of things that have nothing in common save being members of the class.
Is there any advice on the best way to do these things?
Thanks,
John
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (5)
-
John Goerzen
-
Keean Schupke
-
Keith Wansbrough
-
Ralf Laemmel
-
Sebastian Sylvan