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. return (user defined type) confusion? (umptious)
2. Re: return (user defined type) confusion? (Lorenzo Bolla)
----------------------------------------------------------------------
Message: 1
Date: Thu, 12 Apr 2012 16:08:10 +0100
From: umptious <[email protected]>
Subject: [Haskell-beginners] return (user defined type) confusion?
To: [email protected]
Message-ID:
<CAE20bNsNmnp2FF_DnTmqhoRKf=dtsm5qakmq_f6ceo-awjx...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"
I'm bashing together a simple command line geometry thing that let's you
create shapes, move them around them, delete and edit them, test for
intersections, etc. The motivation is to get a grip on Haskell IO and how
it interacts with user defined datatypes. I'm using GHC.
The problem, which I've tried to show as simply as possible in the
abstracted code below, is that something seems to go horribly wrong with
un-boxing (is this the correct terminology?) user defined type X's from
IO(X)'s. In the example below:
- enterCircle makes a Shape using the Circle cstr and boxes it in a return.
And the type checker is happy with the function.
- But when the Shape is un-boxed in mainLoop then Haskell's type system (or
GHC's?) has lost track of its Shapeness. Instead it sees it as a
Pt2->Float. Which makes some sort of sense, but is useless (or at least
needs ugly hacks to overcome) if you want to put your Circle in a List of
Shapes.
- Even worse then the loss of Shapeness is that Haskell is letting me type
enterCircle as returning an IO(Shape) - indeed that's what :t gives me in
GCHI - but then disagrees with this type in mainLoop! This isn't what I was
expecting from the vaunted Haskell type system; can someone explain this
contradiction?
So. Does return fail to wrap up type info about user defined types in
general? Is this correct Haskell behaviour? Or have I done something wrong?
If I haven't done something wrong, is there a standard idiom for overcoming
this? I suppose I could use a show to convert the Circle to a string and
then a read to convert it back in mainLoop's where, but this will mean
uglier branching than I planned (the idea was to have a Map of fns that
return shapes and just one branch in mainLoop to handle every kind of
shape.) And it seems to make something of a nonsense of Haskell's type
system as the entire Shape hierarchy will be reduced to IO(String) for
these operations.
import Data.Map as Map
data Pt2 = Pt2 {x::Float, y::Float} deriving (Show, Read)
data Shape = Circle {origin::Pt2, radius::Float}
| Square {origin::Pt2, side ::Float}
| Rect {origin::Pt2, other ::Pt2}
deriving (Show, Read)
enterCircle :: IO(Shape)
enterCircle = return (r) -- needs to rtn io (shape) because will take input
here
where r = Circle{origin=Pt2{x=1,y=2}, radius=4}
mainLoop :: [Shape] -> IO (String)
mainLoop shapes = do
putStrLn "?"
cmd <- getLine
if cmd=="q"
then
return ("done")
else do
y <- enterCircle
mainLoop shapes'
where shapes' = y : shapes
main = mainLoop []
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20120412/fa2e2c0f/attachment-0001.htm>
------------------------------
Message: 2
Date: Thu, 12 Apr 2012 16:30:36 +0100
From: Lorenzo Bolla <[email protected]>
Subject: Re: [Haskell-beginners] return (user defined type) confusion?
To: umptious <[email protected]>
Cc: [email protected]
Message-ID: <20120412153036.GF25820@dell>
Content-Type: text/plain; charset=us-ascii
It has to do with the scope of "where" in your mainloop.
See comments inline.
On Thu, Apr 12, 2012 at 04:08:10PM +0100, umptious wrote:
>
>
> import Data.Map as Map
>
> data Pt2 = Pt2 {x::Float, y::Float} deriving (Show, Read)
>
> data Shape = Circle {origin::Pt2, radius::Float}
> | Square {origin::Pt2, side ::Float}
> | Rect {origin::Pt2, other ::Pt2}
> deriving (Show, Read)
>
> enterCircle :: IO(Shape)
> enterCircle = return (r) -- needs to rtn io (shape) because will take input
> here
> where r = Circle{origin=Pt2{x=1,y=2}, radius=4}
>
>
> mainLoop :: [Shape] -> IO (String)
> mainLoop shapes = do
> putStrLn "?"
> cmd <- getLine
> if cmd=="q"
> then
> return ("done")
> else do
> y <- enterCircle
This "y" shades the Pt2 accessor "y".
> mainLoop shapes'
> where shapes' = y : shapes
This where thinks that "y" is actually the Pt2 accessor "y".
An easy fix would be to rewrite this line as:
> mainLoop $ y: shapes
Or mess with tabs to get the right scope for "where"...
hth,
L.
--
Lorenzo Bolla
http://lbolla.info
------------------------------
_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners
End of Beginners Digest, Vol 46, Issue 16
*****************************************