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. Non-recursive binding expression ([email protected])
2. Re: Non-recursive binding expression (Will Ness)
3. Re: Re: Non-recursive binding expression (Brent Yorgey)
4. Re: clarification on IO (Will Ness)
5. Re: clarification on IO (Thomas Davie)
6. Catching Exceptions in Haskell (Bjoern Brandenburg)
7. Re: Non-recursive binding expression (Will Ness)
8. Re: Non-recursive binding expression (Ertugrul Soeylemez)
----------------------------------------------------------------------
Message: 1
Date: Sat, 28 Feb 2009 08:27:45 -0300
From: [email protected]
Subject: [Haskell-beginners] Non-recursive binding expression
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=iso-8859-1
Hello.
Is there any non-recursive binding expression in Haskell?
Something that would allow me to write, for instance,
test = let' xs = [] in
let' xs = 3 : xs in
let' xs = 8 : xs in
let' xs = 7 : xs in
xs
Here let' is an hypothetical construction similar to let, except that it
would be non-recursive. In the example, the value of test would be
[7,8,3].
So, is there something in this line in Haskell?
Regards,
José Romildo
------------------------------
Message: 2
Date: Sat, 28 Feb 2009 17:19:03 +0000 (UTC)
From: Will Ness <[email protected]>
Subject: [Haskell-beginners] Re: Non-recursive binding expression
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8
<j.romildo <at> gmail.com> writes:
>
> Hello.
>
> Is there any non-recursive binding expression in Haskell?
>
> Something that would allow me to write, for instance,
>
> test = let' xs = [] in
> let' xs = 3 : xs in
> let' xs = 8 : xs in
> let' xs = 7 : xs in
> xs
>
> Here let' is an hypothetical construction similar to let, except that it
> would be non-recursive. In the example, the value of test would be
> [7,8,3].
>
> So, is there something in this line in Haskell?
>
> Regards,
>
> José Romildo
>
Well, it's not a nice thing to do (probably), but you can write
test = head $
do xs <- [ [] ]
xs <- [ 3:xs ]
xs <- [ 8:xs ]
xs <- [ 7:xs ]
return xs
------------------------------
Message: 3
Date: Sat, 28 Feb 2009 13:01:56 -0500
From: Brent Yorgey <[email protected]>
Subject: Re: [Haskell-beginners] Re: Non-recursive binding expression
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii
On Sat, Feb 28, 2009 at 05:19:03PM +0000, Will Ness wrote:
> <j.romildo <at> gmail.com> writes:
>
> >
> > Hello.
> >
> > Is there any non-recursive binding expression in Haskell?
> >
> > Something that would allow me to write, for instance,
> >
> > test = let' xs = [] in
> > let' xs = 3 : xs in
> > let' xs = 8 : xs in
> > let' xs = 7 : xs in
> > xs
>
> Well, it's not a nice thing to do (probably), but you can write
>
> test = head $
> do xs <- [ [] ]
> xs <- [ 3:xs ]
> xs <- [ 8:xs ]
> xs <- [ 7:xs ]
> return xs
>
The correct answer is no. Life is pain. Anyone who says otherwise is
selling something. ;)
Assignment in Haskell is not destructive update---it assigns a name to
a value, and they become one flesh, until parted by death (i.e. the
end of their lexical scope). The only reason Will's code works is
that each line creates a new lexical scope, and each xs shadows the
previous one.
To do what you want, you have to give each thing a new name, something
like this:
test = let xs = []
xs' = 3 : xs
xs'' = 8 : xs'
xs''' = 7 : xs''
in xs'''
"But this is horribly painful!" you cry. Of course it is! Giving
names to things you don't want to keep is always painful (like when
your child names the almost-dead raccoon you find in the street, which
is just going to die or be given to an animal shelter anyway).
So, why not just avoid naming things you don't want?
test = (7:) . (8:) . (3:) $ []
Ah, that's better! We just thread some intermediate values through a
chain of composed functions. Each function does its little bit of
modification and passes the intermediate value along to the next
function, and the intermediate values are never given names.
-Brent
------------------------------
Message: 4
Date: Sat, 28 Feb 2009 19:13:01 +0000 (UTC)
From: Will Ness <[email protected]>
Subject: [Haskell-beginners] Re: clarification on IO
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii
Michael Easter <codetojoy <at> gmail.com> writes:
>
>
> Q1: The web page mentions that normal Haskell functions cannot cause side-
effects, yet later talks about
> side-effects with putStrLn. I assume the key point here that IO actions are,
by definition, _not_ normal functions?
The way I look at it, a monad is a way of saying, "we'll be carrying along and
combining, in some specific manner, values with some extra information attached
to them, which most functions don't need to worry about". _How_ it carries
along these values and combines them, and the corresponding hidden data, is
what makes the particular Monad type to be what it is.
Let's call a function an M-action function if its type is (:: a -> M b), for
some monad M. Such functions can get chained by M's bind, as in
( (x :: M a) >>= (f :: a -> M b) ) :: M b
M can also provide us with special functions that will reveal its hidden
information, e.g. (reveal :: (hidden_stuff -> a -> M b) -> a -> M b), so that
for a user-defined (g :: hidden_stuff -> a -> M b), (reveal g) can be chained
and the function g will get called providing us with the information, if the
monad so chooses.
For example, Philip Wadler in his paper "The Essence of Functional Programming"
gives an example of a "position" monad P which defines its own special
function, resetPosition, enabling us to reset its hidden data - in this case, a
code position.
IO primitives like putStrLn, instead of revealing anything to us, carry along a
promise to take notice of the value they are supplied with and to perform an
actual real world IO action with them, when called upon to do so by the system.
We can create chains of IO-action functions and store them in variables,
without them getting executed by the system - and thus without causing any real-
world IO action, e.g.
x = do {putStrLn "1";return 2}
somewhere in your program will just create a definition that will just hold an
IO-action function in it.
It's just a feature of an interactive loop that when is sees a value of type
(IO a) it will not just return it, but will also execute the promised actions
held inside it:
-- in HUGS --
Prelude> [ do {putStrLn "1";return 2} ] -- a value just gets returned
[<<IO action>>] :: [IO Integer]
Prelude> do {putStrLn "1";return 2} -- actual IO action performed
1 :: IO Integer
-- in GHCi --
Prelude> let x=[do {putStrLn "1"; return 2}]
Prelude> head x
1
2
Prelude> head x
1
2
Prelude> :t it
it :: Integer
The same goes to the special identifier (main :: IO a) that will also get
treated in this special way - getting executed on sight. :)
------------------------------
Message: 5
Date: Sat, 28 Feb 2009 20:40:46 +0100
From: Thomas Davie <[email protected]>
Subject: Re: [Haskell-beginners] clarification on IO
To: Chadda? Fouch? <[email protected]>
Cc: [email protected], Michael Easter <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain; charset=WINDOWS-1252; format=flowed;
delsp=yes
On 28 Feb 2009, at 10:13, Chaddaï Fouché wrote:
> On Sat, Feb 28, 2009 at 3:50 AM, Michael Easter
> <[email protected]> wrote:
>> Q1: The web page mentions that normal Haskell functions cannot cause
>> side-effects, yet later talks about
>> side-effects with putStrLn. I assume the key point here that IO
>> actions are,
>> by definition, _not_ normal functions?
>
> putStrLn is a perfectly pure function (there is no other kind in
> Haskell), it takes a String and return a value of type IO (), this
> value is like any other first class object in Haskell and can be
> manipulated as thus, the only difference is that this value can be
> computed in the context of the IO monad and then have a side-effect.
> The value of type IO a are often called actions but they aren't
> fundamentally different from other values.
Note, take this information with a pretty gigantic grain of salt. It
is true that you are writing a pure program when using IO functions,
but you should probably think about what that means.
The advantage of pure programs is that you get certain neat benefits
like not having to bother about "am I doing this in the right order"
or "will the system do weird random shit while this function is
executed". This is not true about IO typed functions. An IO typed
function generates an IO value which the runtime runs. That means,
that they essentially get us no further forward than C. In C we write
pure functions called C preprocessor macros. These pure functions
generate imperative programs (C programs) which are run by the runtime
(the C compiler and your OS). This is no different to IO.
So, the lesson IO is in theory pure. But that doesn't mean that we
get all the nice benefits of functional programming while using the IO
monad. One can say pretty much the same thing about all stateful
monads, although IO is by far the worse, in that the state can be
influenced by chunks of reality totally outside your control.
Bob
------------------------------
Message: 6
Date: Sat, 28 Feb 2009 15:57:41 -0500
From: Bjoern Brandenburg <[email protected]>
Subject: [Haskell-beginners] Catching Exceptions in Haskell
To: [email protected]
Message-ID:
<[email protected]>
Content-Type: text/plain; charset=ISO-8859-1
Hi all,
I'm struggling to figure out how to catch an exception in Haskell.
Eventually, what I want to do is to use the Control.Macho library
(from Hackage) to parse binaries on Mac OS X. Naturally, I would like
my program to gracefully handle corrupted files or files that aren't
binaries. So I need to catch exceptions if the parsing with Data.Macho
fails...
This is what I've got so far:
http://hpaste.org/fastcgi/hpaste.fcgi/view?id=1877#a1877
Digression: Note that if I leave out the `foo e` call, then I get
scratch.hs:21:9:
Ambiguous type variable `e' in the constraint:
`Exception e' arising from a use of `try' at scratch.hs:21:9-11
Probable fix: add a type signature that fixes these type variable(s)
I find this somewhat counter-intuitive; this is also not discussed in
the book "Real-World Haskell" (at least I haven't found it), which is
what I'm using to learn Haskell. What is the best way to get around
this?
Back to my problem. The program produces the following output:
$ runghc scratch.hs
Testing Pure... Caught a bad exception: abort via error
Testing Macho... No exception occured, the result is:
scratch.hs: too few bytes. Failed reading at byte position 4
This counter-intuitive in at least two ways:
1) How can it fail at position 4 in an empty string? That looks like a
sloppy error message too me; why doesn't it report the actually
failing position?
2) Why can I catch an exception raised with an error in my own code,
but not the one raised by Data.Binary.Get? Looking at
http://hackage.haskell.org/packages/archive/binary/0.5/doc/html/src/Data-Binary-Get.html#failDesc
, an exception within Data.Binary.Get is also raised with error. What
is the difference?
Why am I seeing what I'm seeing, and how should I be doing it in the
first place?
Thanks in advance,
Bjoern
------------------------------
Message: 7
Date: Sat, 28 Feb 2009 22:31:37 +0000 (UTC)
From: Will Ness <[email protected]>
Subject: [Haskell-beginners] Re: Non-recursive binding expression
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii
Brent Yorgey <byorgey <at> seas.upenn.edu> writes:
>
> On Sat, Feb 28, 2009 at 05:19:03PM +0000, Will Ness wrote:
> > <j.romildo <at> gmail.com> writes:
> >
> > >
> > > Hello.
> > >
> > > Is there any non-recursive binding expression in Haskell?
> > >
> > > Something that would allow me to write, for instance,
> > >
> > > test = let' xs = [] in
> > > let' xs = 3 : xs in
> > > let' xs = 8 : xs in
> > > let' xs = 7 : xs in
> > > xs
> >
> > Well, it's not a nice thing to do (probably), but you can write
> >
> > test = head $
> > do xs <- [ [] ]
> > xs <- [ 3:xs ]
> > xs <- [ 8:xs ]
> > xs <- [ 7:xs ]
> > return xs
> >
>
> The correct answer is no. Life is pain. Anyone who says otherwise is
> selling something. ;)
>
> Assignment in Haskell is not destructive update---it assigns a name to
> a value, and they become one flesh, until parted by death (i.e. the
> end of their lexical scope). The only reason Will's code works is
> that each line creates a new lexical scope, and each xs shadows the
> previous one.
That's what I understood the OP wanted - Scheme's LET, not LETREC, allowing for
shadowing. I was suprised let-statement in do chain didn't work that way. I
expected it to be equivalent to a kind of code above, since each new line in do
block represents a nested function in explicit bind notation, and nested
function binding definitely provides for non-recursive let kind of argument
binding, with shadowing.
I thought the whole point of having special let statement in do notation was
not to have to write the kind of code above with singleton lists. Since we have
shadowing there, it should've been so in let-statements too. Isn't it?
>
> To do what you want, you have to give each thing a new name, something
> like this:
>
> test = let xs = []
> xs' = 3 : xs
> xs'' = 8 : xs'
> xs''' = 7 : xs''
> in xs'''
>
> "But this is horribly painful!" you cry. Of course it is! Giving
> names to things you don't want to keep is always painful (like when
> your child names the almost-dead raccoon you find in the street, which
> is just going to die or be given to an animal shelter anyway).
>
> So, why not just avoid naming things you don't want?
>
> test = (7:) . (8:) . (3:) $ []
>
> Ah, that's better! We just thread some intermediate values through a
> chain of composed functions. Each function does its little bit of
> modification and passes the intermediate value along to the next
> function, and the intermediate values are never given names.
>
> -Brent
>
BTW could there be a use for something like
infixl 1 #
x # f = f x -- (#) = flip ($)
to have the direct data flow reflected in our code, so that your code would
become
test = [] # (3:) # (8:) # (7:)
maybe sometimes it's more natural to think of data being "piped through" the
chain of functions, and to write them down in forward, not reverse order of
application?
------------------------------
Message: 8
Date: Sun, 1 Mar 2009 00:44:31 +0100
From: Ertugrul Soeylemez <[email protected]>
Subject: [Haskell-beginners] Re: Non-recursive binding expression
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=US-ASCII
Will Ness <[email protected]> wrote:
> BTW could there be a use for something like
>
> infixl 1 #
>
> x # f = f x -- (#) = flip ($)
>
> to have the direct data flow reflected in our code, so that your code
> would become
>
> test = [] # (3:) # (8:) # (7:)
>
> maybe sometimes it's more natural to think of data being "piped
> through" the chain of functions, and to write them down in forward,
> not reverse order of application?
I think, it's more natural to think in terms of functions, and often the
argument to a function is not just something as simple as [] anyway. If
you want to think in chaining instead of composition, you can use arrow
sequencing (>>>) instead of function composition (.):
import Control.Arrow
test = (3:) >>> (8:) >>> (7:) $ []
Greets,
Ertugrul.
--
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/
------------------------------
_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners
End of Beginners Digest, Vol 8, Issue 31
****************************************