accessor function scope

I'm coming from the OO world and trying to adapt. I've noticed that if I declare two types like this data Thing1 = Thing1 { itemPos :: Int } data Thing2 = Thing2 { itemPos :: Int } then I get the error "Multiple declarations of Main.itemPos" However, I can successfully do this: type Pos = ( Int, Int ) type Dimension = ( Int, Int, Int, Int ) data LayoutItem = StaffItem { itemPos :: Pos, itemDim :: Dimension } | TextItem { itemPos :: Pos, itemDim :: Dimension } d1 = TextItem ... d2 = StaffItem ... i1 = itemPos d i2 = itemPos d2 This seems to define itemPos in a way that can sense whether it's dealing with a StaffItem-type LayoutItem or a TextItem-type LayoutItem. I don't know if this would be considered an overloaded operator. However, it does resemble derived class in OO. For that matter, I don't know what the term is for a "StaffItem-type LayoutItem". The type is clearly LayoutItem. "StaffItem" is the constructor. How do you refer to the concept of a LayoutItem constructed via a StaffItem? Again, StaffItem and TextItem resemble derived classes in OO. Any clarification welcome. -Mike

2009/4/7 Michael Mossey
I'm coming from the OO world and trying to adapt.
me too :-)
For that matter, I don't know what the term is for a "StaffItem-type LayoutItem". The type is clearly LayoutItem. "StaffItem" is the constructor. How do you refer to the concept of a LayoutItem constructed via a StaffItem?
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, 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 ...
Any clarification welcome. -Mike
Ciao ----- FB

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, 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 ...
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 class. -- Note: Now I can no longer have any overlapping field names data TextItem = TextItem { tField1, tField2 :: Int } data StaffItem = StaffItem { sField1, sField3 :: Int } 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.

I've noticed that if I declare two types like this
data Thing1 = Thing1 { itemPos :: Int } data Thing2 = Thing2 { itemPos :: Int }
then I get the error "Multiple declarations of Main.itemPos"
Here's something to consider. What's the type of itemPos? In the above code, it can't be itemPos :: Thing1 -> Int because you want to be able to apply it to a Thing2. I suppose the compiler could, behind the scenes, create a typeclass like this: class ItemPosAble a where itemPos :: a -> Int instance ItemPosAble Thing1 where itemPos (Thing1 x) = x instance ItemPosAble Thing2 where itemPos (Thing2 x) = x Then itemPos has type itemPos :: (ItemPosAble t) => t -> Int Maybe that would work, modulo my typos. But it's messy, and it gets messier if itemPos doesn't have the same return type in all examples. It probably makes it harder to produce clear error messages when something goes wrong. There are probably other issues I haven't seen yet. At any rate, just disallowing this kind of "overloading" of the accessor function is simple, and works. As you point out later, you can reuse the name by separating namespaces using modules.
data LayoutItem = StaffItem { itemPos :: Pos, itemDim :: Dimension } | TextItem { itemPos :: Pos, itemDim :: Dimension }
Here the type of itemPos is clearly just itemPos :: LayoutItem -> Pos No problem. Behind the scenes, the compiler is defining it as something like itemPos (StaffItem x _) = x itemPos (TextItem x _) = x
This seems to define itemPos in a way that can sense whether it's dealing with a StaffItem-type LayoutItem or a TextItem-type LayoutItem. I don't
You're right that there's enough information to figure it out in this example code, but the type inference in Haskell doesn't do this kind of ad-hockery.
know if this would be considered an overloaded operator. However, it does resemble derived class in OO.
It's not a bad exercise to compare Haskell to what you already know, but expect it to break down before long. Clear and idiomatic functional design will generally look pretty different from clear and idiomatic OO design. That said, you can do OO stuff in Haskell; it's just not very fun, and generally not needed.
For that matter, I don't know what the term is for a "StaffItem-type LayoutItem". The type is clearly LayoutItem. "StaffItem" is the constructor. How do you refer to the concept of a LayoutItem constructed via a StaffItem?
You can just call it "a StaffItem", I guess. I don't know if there's a common term. But you're right that it's type is LayoutItem. Regards, John

On 2009 Apr 7, at 9:00, John Dorsey wrote:
I've noticed that if I declare two types like this
data Thing1 = Thing1 { itemPos :: Int } data Thing2 = Thing2 { itemPos :: Int }
then I get the error "Multiple declarations of Main.itemPos"
Here's something to consider. What's the type of itemPos? In the above code, it can't be
itemPos :: Thing1 -> Int
because you want to be able to apply it to a Thing2. I suppose the compiler could, behind the scenes, create a typeclass like this:
I think it already does this if you ask for the DisambiguateRecordFields language extension (provided it can tell which one is needed!).
For that matter, I don't know what the term is for a "StaffItem-type LayoutItem". The type is clearly LayoutItem. "StaffItem" is the constructor. How do you refer to the concept of a LayoutItem constructed via a StaffItem?
You can just call it "a StaffItem", I guess. I don't know if there's a common term. But you're right that it's type is LayoutItem.
Technically LayoutItem is a sum of products and StaffItem is a variant (see http://en.wikipedia.org/wiki/Sum_type for more information). -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
participants (4)
-
Brandon S. Allbery KF8NH
-
Francesco Bochicchio
-
John Dorsey
-
Michael Mossey