accessor function scope

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

accessor function scope

Michael Mossey
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
Reply | Threaded
Open this post in threaded view
|

accessor function scope

Francesco Bochicchio
2009/4/7 Michael Mossey <[hidden email]>

> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090407/2bfbb60a/attachment-0001.htm
Reply | Threaded
Open this post in threaded view
|

accessor function scope

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,
> 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.

Reply | Threaded
Open this post in threaded view
|

accessor function scope

John Dorsey-2
In reply to this post by Michael Mossey
> 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

Reply | Threaded
Open this post in threaded view
|

accessor function scope

Brandon S Allbery KF8NH
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] [hidden email]
system administrator [openafs,heimdal,too many hats] [hidden email]
electrical and computer engineering, carnegie mellon university    KF8NH


-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 195 bytes
Desc: This is a digitally signed message part
Url : http://www.haskell.org/pipermail/beginners/attachments/20090407/163e8167/PGP.bin