
Am Dienstag 07 April 2009 11:47:32 schrieb Michael Mossey:
Francesco Bochicchio wrote:
me too :-)
Again, StaffItem and TextItem resemble derived classes in OO.
To me, they are more close to C union : a data type than can alternatively have different structures,
Both analogies capture some aspects of Haskell types. They're useful if you are aware that they take you only so far.
In your example, LayoutItem is a type name, while StaffItem and TextItem are constructor, that is functions. Saying that a function specializes a type is a bit of a stretch, I think ...
Nevertheless, they can sometime be used to accomplish the same goal : where in OO you define an abstact class and then specialize with concrete classes to model a classification, in haskell you can define a data type with alternate constructors.
I think that data types with alternate constructores are called algebraic data types in haskellese, but I'm not sure of that ...
Yes, they're called algebraic datatypes, but I'm not sure if a type must have more than one constructor to qualify as such.
Here's what I've learned from my investigations, but I welcome any clarifications.
There are a few ways they don't resemble constructors in OO, or unions in C.
They are "constructors", but also "take apart" the item in pattern matching. myfunc (StaffItem pos dimension) = ... myfunc (TextItem pos dimension) = ...
You can also hide the constructors when you export a module. I could export LayoutItem but not StaffItem and TextItem, meaning that other code would see LayoutItem as a kind of abstract base class.
When you name a field in each constructor (the same name), you can access that field on any LayoutItem without knowing its constructor using the accessor function for that field. This looks a lot like an abstract base class.
data LayoutItem = TextItem { myField :: Int }
| StaffItem { myField :: Int }
x1 = TextItem { myField = 3 } x2 = STaffItem { myField = 4 }
y1 = myField x1 y2 = myField x2
When I tried to make TextItem and StaffItem instances of a class, I got an error. They aren't really types. Only LayoutItem is the type.
instance Eq TextItem where ... ---> ERROR!
instance Eq StaffItem where ...
---> ERROR!
instance Eq LayoutItem where... ---> ok
Right now I'm just confused by how to translate an exising OO design. I'm porting a partially complete Python program to Haskell. There are many options. For instance I could set up a class called LayoutClass, make TextItem and StaffItem their own classes and make them instances of the
"their own types"
class.
-- Note: Now I can no longer have any overlapping field names data TextItem = TextItem { tField1, tField2 :: Int } data StaffItem = StaffItem { sField1, sField3 :: Int }
For fields that are generic enough to be interesting, you can have class HasPosition a where pos :: a -> Position class HasDimension a where dim :: a -> Dimension class HasField1 a where field1 :: a -> Int instance HasField1 TextItem where field1 (TextItem f1 _) = f1
class LayoutClass a where access1 :: a -> Int
instance LayoutClass TextItem where access1 (TextItem t) = tField1 t
instance LayoutClass StaffItem where access1 (StaffItem s ) = sField1 s
Or put everything in its own module and use qualified names. Probably the best choice for future considerations.
Consider also the "class HasWhatever" approach, sometimes it's better than qualified names.