
Michael Mossey wrote:
For example, if I want to create LayoutItem and name its coordinates x and y... Then later I can refer to p.x and p.y. I can also create other classes and name *their* member variables x and y, with no confusion.
There are two ways to share names in Haskell. One way, which is most similar to the OO approach, is to use encapsulation. Haskell uses modules for encapsulation and namespace control. However, GHC currently requires each module to reside in a separate source file (even though that is not required by the standard). When you use this method, you need to use dotted names to qualify them, as in your OO example. If only one version of a name is used in a given module, you can choose to import that name unqualified into the namespace of that module. The other approach is using the class system: class Coordinates a where x :: a -> Int y :: a -> Int data LayoutItem = LayoutItem { layoutItemX, layoutItemY :: Int } instance Coordinates LayoutItem where x = layoutItemX y = layoutItemY data Notehead = Notehead { noteheadItemX, noteheadItemY :: Int } instance Coordinates Notehead where x = NoteheadX y = NoteheadY Note that using this approach, the types of x and y always need to have exactly the same shape: a -> Int, where a is the type for which you are declaring the class instance. You can't use Int for one type and Float for another, for example. You can get around that restriction using Haskell extensions such as type families, or multiparameter classes and functional dependencies. With the approach, you do not qualify the names. You just re-use the names, and the type checker figures out what you mean from the context. In case of ambiguity, you use explicit type signatures to clarify the situation. Hope this helps, Yitz