[Haskell-beginners] accessor function scope

Daniel Fischer daniel.is.fischer at web.de
Tue Apr 7 09:15:00 EDT 2009


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.




More information about the Beginners mailing list