Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1. Re:  accessor function scope (Michael Mossey)
   2. Re:  accessor function scope (John Dorsey)
   3. Re:  accessor function scope (Daniel Fischer)
   4. Re:  accessor function scope (Brandon S. Allbery KF8NH)
   5. Re:  accessor function scope (Brandon S. Allbery KF8NH)
   6.  Re: CORRECTED: making translation from   imperative code]
      (Heinrich Apfelmus)
   7.  Local Haskell meeting, Halle/Saale, Germany,     June 12
      (Janis Voigtlaender)


----------------------------------------------------------------------

Message: 1
Date: Tue, 07 Apr 2009 02:47:32 -0700
From: Michael Mossey <[email protected]>
Subject: Re: [Haskell-beginners] accessor function scope
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed



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.



------------------------------

Message: 2
Date: Tue, 7 Apr 2009 09:00:54 -0400
From: John Dorsey <[email protected]>
Subject: Re: [Haskell-beginners] accessor function scope
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii

> 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



------------------------------

Message: 3
Date: Tue, 7 Apr 2009 15:15:00 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] accessor function scope
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="iso-8859-1"

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.




------------------------------

Message: 4
Date: Tue, 7 Apr 2009 13:31:40 -0400
From: "Brandon S. Allbery KF8NH" <[email protected]>
Subject: Re: [Haskell-beginners] accessor function scope
To: John Dorsey <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="us-ascii"

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] [email protected]
system administrator [openafs,heimdal,too many hats] [email protected]
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-0001.bin

------------------------------

Message: 5
Date: Tue, 7 Apr 2009 13:38:16 -0400
From: "Brandon S. Allbery KF8NH" <[email protected]>
Subject: Re: [Haskell-beginners] accessor function scope
To: Daniel Fischer <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="us-ascii"

On 2009 Apr 7, at 9:15, Daniel Fischer wrote:
> Yes, they're called algebraic datatypes, but I'm not sure if a type  
> must have
> more than one constructor to qualify as such.

An ADT is any type expressible by a combination of sum and product  
types, IIRC.  Single constructor types are product types, multiple  
constructors are sums of product types.  (Note that this leaves out  
"data Nil"; that's why it's an extension.  "data Nil = Nil" is  
vacuously an ADT.)

-- 
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [email protected]
system administrator [openafs,heimdal,too many hats] [email protected]
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/9275ed20/PGP-0001.bin

------------------------------

Message: 6
Date: Wed, 08 Apr 2009 01:29:22 +0200
From: Heinrich Apfelmus <[email protected]>
Subject: [Haskell-beginners] Re: CORRECTED: making translation from
        imperative code]
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1

Michael Mossey wrote:
> Okay, I read all of your email, and there is one problem. My layout
> problem is more complex than I communicated at first. Let me give a more
> detailed example:
> 
> staff 1:  xxxx|xxxx  x|x
> staff 2:     x|xx xxxx|xx
> staff 3:                  x|x
>               a       b    c
> 
> There are two additional concerns to what you coded up. Notice that
> parts of events on different staves are allowed to overlap. To determine
> the spacing from a to b, one has to know the widths of items on each
> staff to see that they they can be placed with some overlap but won't
> collide. They can't be treated strictly as a compound item and "going
> blind" to the parts that make them up.
> 
> Secondly, look at the item on staff 3 at c. It has no prior item to
> avoid colliding with, and no items on other staves to line up with, but
> there is still a constraint on its position: c > b (by some amount that
> can be experimented with).

No problem. :)

Reading your code, I'd generally recommend a higher-level approach
focusing on *abstraction*. Primitive recursion can do the job, but it's
error-prone and tedious and best avoided.

> -- Item is a pair giving left width and right width.
> type Item = (Int, Int)
> -- Chunk represents items that must align.
> -- There may not be one on every staff,
> -- hence the use of Maybe
> type Chunk = [ Maybe Item ]

Abstraction starts with using type synonyms like

   type Pos   = Int
   type Width = Pos

that indicate what the parameter denotes, not how it's represented by
the computer. [Int]  is less descriptive than  [Pos]  (a list of
absolute coordinates), because it could also mean  [Width]  (a list of
relative coordinates). For instance, it's possible to add two widths,
but adding two positions should be a type error, you may only advance a
position by a width.


Also, I think that  Chunk  is too generic a name, but I don't have a
good replacement for now. But see below.


Abstraction is also key to solving the new problem description with the
same algorithm as the old one. In particular, our goal is to implement
the function  align  just like the old one.

The core abstraction is that of an *extent*. It's simply a list of widths

   type Extent = [Width]

representing a vertical group of bars.

   xxxx|      |xxxx
     xx|  or  |xx        =  [4,2,3]
    xxx|      |xxx

We don't specify whether they are ragged to the right or left. The
define the  width  of an extent to be the maximum width of its bars

   width :: Extent -> Width
   width = maximum

A  Chunk  is of course just a pair of extents, one to the left and one
to the right

   extents :: Chunk -> (Extent,Extent)
   extents = unzip . map (maybe (0,0) id)

Now,  align  is structured just like before, calculating the gaps
between different items

   align :: [(Extent, Extent)] -> [Pos]
   align xs = scanl (+) (width l) gaps
      where
      (l:ls, rs) = unzip xs
      gaps       = zipWith fit rs ls

However, extents are now fitted together with

   fit :: Extent -> Extent -> Width
   fit xs ys = (+1) . maximum . zipWith (+) xs ys

The previous code can be interpreted as fitting extents together with

   fit xs ys = maximum xs + maximum ys

Different definitions of  fit  yield different layouts algorithms.


I'm not happy with the definition of  align  yet, because the specifics
of laying out extents are present in two places, namely  width  and  fit
 instead of just one, namely  fit . This can be remedied by noting that
the purpose of  width  is to fit the first extent to the *left
boundary*. In other words,

   width = fit (repeat 0)

(assuming that  fit  is able to crop and infinite list of widths to the
proper size). Thus, we have

   align xs = scanl1 (+) gaps
      where
      (ls,rs)  = unzip xs
      boundary = repeat 0
      gaps     = zipWith fit (boundary:rs) ls



In the end, both  align  and your  layout3  functions do exactly the
same calculations, of course, but by virtue of abstraction, the
correctness and structure of the former is self-evident.

> layout3 :: [ Chunk ] -> [ Int ]
> layout3  cs        = layout3' cs (replicate (length cs) 0) 0
> 
> layout3' :: [ Chunk ] -> [ Int ] -> Int -> [ Int ]
> layout3' [] _ _         = []
> layout3' (c:cs) rs minP = p : layout3' cs rs' (p + 1) where
>    p = maximum $ minP : (map place (zip c rs))
>    rs' = map (advance p) c
>    place (item, r) = case item of
>            Just ( left, right ) -> r + left + 1
>            _                    -> 0
>    advance p item  = case item of
>            Just ( left, right ) -> p + right + 1
>            _                    -> p



Two remarks on the code for pretty printing:

> drawLayout :: [ Chunk ] -> [ Int ] -> String
> drawLayout cs pos = unlines $ makeLines cs pos where
> 
>    makeLines :: [ Chunk ] -> [ Int ] -> [ String ]
>    makeLines cs@(cs1:_) pos
>      | null cs1   = []
>      | otherwise  = makeLine (map head cs) pos :
>                     makeLines (map tail cs) pos

This is basically a function known as  transpose  (from Data.List).
Also, let's reorder the parameters.

     makeLines :: [Pos] -> [Chunk] -> [String]
     makeLines pos = map (makeLine pos) . transpose

>    makeLine :: [ Maybe Item ] -> [ Int ] -> String
>    makeLine items pos = foldl addItem [] (zip items pos)
>
>    addItem :: String -> ( Maybe Item, Int ) -> String
>    addItem s ( item, p ) =
>      let le = length s in case item of
>        Just ( l, r ) -> s ++ (replicate (p - le - l)  ' ') ++
>                         (replicate l 'x') ++ "|" ++ (replicate r 'x')
>        _             -> s
>
> data1 = [ [ Just (2,2), Just(1,1), Just (2,3 ) ],
>           [ Just (1,1),  Just (3,4), Just(1,1) ],
>           [ Just (4,4), Nothing, Just (1,1) ] ]
> 
> answer = drawLayout data1 (layout3 data1)
> main = do putStr answer

  main = putStr answer   -- no  do  required

> *Main> main
>  xx|xx  x|x xxxx|xxxx
>   x|x xxx|xxxx
>  xx|xxx x|x    x|x
> *Main>


Regards,
apfelmus

--
http://apfelmus.nfshost.com





------------------------------

Message: 7
Date: Wed, 08 Apr 2009 08:09:11 +0200
From: Janis Voigtlaender <[email protected]>
Subject: [Haskell-beginners] Local Haskell meeting, Halle/Saale,
        Germany,        June 12
To: [email protected], [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

[Apologies for German announcement text...]

---------------------------------------------
HaL4 : Haskell - Tutorial + Workshop + Party
am Freitag, dem 12. Juni 2009, in Halle/Saale
---------------------------------------------

Das traditionsreiche HaL-Treffen bietet eine gute Mischung
von Haskell-bezogenen Themen aus Forschung, Anwendung und Lehre
mit vielen Möglichkeiten zu Diskussion und Unterhaltung
bei der anschließenden Party. Der Workshop wird in diesem Jahr
ergänzt durch Tutorien für Haskell-Ein- und Umsteiger.
Diesmal findet das Treffen in Halle/Saale im Institut für Informatik
der Martin-Luther-Universität Halle-Wittenberg statt. Wir planen:

10 - 13 Uhr: Tutorien
15 - 19 Uhr: Fachvorträge
19 - 22 Uhr: Grillparty

Wir freuen uns auf rege Teilnahme sowie spannende Vorträge mit heißen
Diskussionen und bitten um Vortragsanmeldungen bis zum 8. Mai.
Gedacht sind 4 mal je 30 min Vortrag + 30 min Diskussion.
Weitere Informationen auf http://www.iba-cg.de/hal4.html

-- 
Dr. Janis Voigtlaender
http://wwwtcs.inf.tu-dresden.de/~voigt/
mailto:[email protected]




------------------------------

_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 10, Issue 7
****************************************

Reply via email to