Heterogenous collections: Difference between revisions
mNo edit summary |
BrettGiles (talk | contribs) (Editting and formatting) |
||
Line 6: | Line 6: | ||
=== The problem === | === The problem === | ||
Does some kind of collection of objects with different types in Haskell exist? Obviously, tuples are an example, but they have a fixed length. To compare tuples vs lists: | |||
exist? | |||
{| border="1" cellpadding="2" align="center" | |||
|- | |||
!Tuples!!Lists | |||
|+ | |||
|Heterogeneous||Homogeneous | |||
|+ | |||
|Fixed length (per tuple type)||Variable length | |||
|+ | |||
|Always finite||May be unending | |||
|} | |||
However, the need is for heterogeneous and non-fixed length. When one is used to Java, with its loose typing of collections,not having this immediately and | |||
used | easily available seems strange. As an example, the need is for something like LinkedList<Object> from java. | ||
=== Algebraic | === Algebraic datatypes === | ||
If the number of | If the number of [[type]]s to cover is fixed, then the problem can be solved by a list of data types such as | ||
<haskell> | <haskell> | ||
Line 42: | Line 46: | ||
</haskell> | </haskell> | ||
This is a very basic solution, and often preferable. Limitations: You | This is a very basic solution, and often preferable. Limitations: You have to type-switch all the time if you want to do anything with the objects in the List, and the collections are clumsy to extend by new types. | ||
have to type-switch all the time if you want to do anything with the | |||
objects in the List, and the collections are clumsy to extend by new | |||
types. | |||
=== HLists, OOHaskell, | === HLists, OOHaskell, type-level programming === | ||
This is the cleanest solution, but very advanced and a little | This is the cleanest solution, but very advanced and a little restrictive. Read these two articles: | ||
restrictive. Read these two articles: | |||
* http://homepages.cwi.nl/~ralf/HList/ | * http://homepages.cwi.nl/~ralf/HList/ | ||
Line 59: | Line 59: | ||
There is also some related material here: | There is also some related material here: | ||
* | * [[Extensible record]] | ||
=== Existential | === [[Existential types]] === | ||
Depending on | Depending on needs and comfort level with fancier types, the existential approach to ADTs might solve the problem. The following code is a demonstration you can cut-and-paste-and-run. | ||
existential approach to ADTs might solve | |||
code is a demonstration you can cut-and-paste-and-run. | |||
This is example akin to upcasting in Java to an interface that lets | This is example akin to upcasting in Java to an interface that lets you print things. That way you know how to print every object (or do whatever else it is you need to do) in the list. Beware: there is no safe downcasting (that's what Typeable would be for); that would likely be more than you need. | ||
you print things. That way you know how to print every object (or do | |||
whatever else it is you need to do) in the list. Beware: there is no | |||
safe downcasting (that's what Typeable would be for); that would | |||
likely be more than you need. | |||
There are other ways to do this with existentials (e.g. bounded | There are other ways to do this with existentials (e.g. bounded existentials), but this is what came out of my head when I read your post. Existentials seems to be the "Haskellish" way to reduce a heterogenous list to a collection of objects with common operations. [[HList]] would be the Haskellish way for more static and flexible assurances. | ||
existentials), but this is what came out of my head when I read your | |||
post. Existentials seems to be the "Haskellish" way to reduce a | |||
HList would be the Haskellish way for more static and flexible | |||
assurances. | |||
<haskell> | <haskell> |
Revision as of 20:12, 17 November 2006
This page is a very hasty and ad-hoc summary of a common discussion on the haskell-cafe list. If you find it hard to read, please complain there and somebody hopefully will come to help.
The problem
Does some kind of collection of objects with different types in Haskell exist? Obviously, tuples are an example, but they have a fixed length. To compare tuples vs lists:
Tuples | Lists |
---|---|
Heterogeneous | Homogeneous |
Fixed length (per tuple type) | Variable length |
Always finite | May be unending |
However, the need is for heterogeneous and non-fixed length. When one is used to Java, with its loose typing of collections,not having this immediately and easily available seems strange. As an example, the need is for something like LinkedList<Object> from java.
Algebraic datatypes
If the number of types to cover is fixed, then the problem can be solved by a list of data types such as
data T =
ConsInt Int
| ConsString String
| ConsChar Char
or:
data Object = IntObject Int | StringObject String
objectString :: Object -> String
objectString (IntObject v) = show v
objectString (StringObject v) = v
main = mapM_ (putStrLn . objectString) [(IntObject 7), (StringObject "eight")]
This is a very basic solution, and often preferable. Limitations: You have to type-switch all the time if you want to do anything with the objects in the List, and the collections are clumsy to extend by new types.
HLists, OOHaskell, type-level programming
This is the cleanest solution, but very advanced and a little restrictive. Read these two articles:
There is also some related material here:
Existential types
Depending on needs and comfort level with fancier types, the existential approach to ADTs might solve the problem. The following code is a demonstration you can cut-and-paste-and-run.
This is example akin to upcasting in Java to an interface that lets you print things. That way you know how to print every object (or do whatever else it is you need to do) in the list. Beware: there is no safe downcasting (that's what Typeable would be for); that would likely be more than you need.
There are other ways to do this with existentials (e.g. bounded existentials), but this is what came out of my head when I read your post. Existentials seems to be the "Haskellish" way to reduce a heterogenous list to a collection of objects with common operations. HList would be the Haskellish way for more static and flexible assurances.
{-# OPTIONS -fglasgow-exts #-}
module Test where
data PrintPackage = forall a . PrintPackage a (a -> String)
instance Show PrintPackage where
show (PrintPackage val showMethod) = showMethod val
list = [ PrintPackage 3 show
, PrintPackage "string" show
, PrintPackage 3.4 show
]
main = print list