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. How to unnest "do" (Martin Drautzburg)
2. Re: How to unnest "do" (Ertugrul S?ylemez)
3. Re: How to unnest "do" (David McBride)
4. Re: How to unnest "do" (Emmanuel Touzery)
5. Re: How to unnest "do" (Brent Yorgey)
6. Re: How to unnest "do" (Emmanuel Touzery)
----------------------------------------------------------------------
Message: 1
Date: Sun, 27 Jan 2013 18:27:48 +0100
From: Martin Drautzburg <[email protected]>
Subject: [Haskell-beginners] How to unnest "do"
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="us-ascii"
Hello all,
in the code snippet below, is there a way to factor out the second "do"?
import System (getArgs)
main :: IO ()
main = do
args <- getArgs
case args of
[fname] -> do fstr <- readFile fname
let nWords = length . words $ fstr
nLines = length . lines $ fstr
nChars = length fstr
putStrLn . unwords $ [ show nLines
, show nWords
, show nChars
, fname]
_ ->putStrLn "usage: wc fname"
------------------------------
Message: 2
Date: Sun, 27 Jan 2013 20:43:58 +0100
From: Ertugrul S?ylemez <[email protected]>
Subject: Re: [Haskell-beginners] How to unnest "do"
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="us-ascii"
Hi there Martin,
since the nested 'do' makes sense, there is little you can do about it.
However, you can make the code more beautiful and restructure it a bit.
This is how I would have written it:
import Control.Applicative
import System.Environment
import System.IO
stats :: String -> String
stats =
unwords .
sequence [show . length . words,
show . length . lines,
show . length]
main :: IO ()
main = do
args <- getArgs
case args of
[fn] -> fmap stats (readFile fn) >>= putStrLn
_ -> hPutStrLn stderr "Usage: wc FNAME"
This improves the statistics code slightly, but uses some monadic
machinery you may not be familiar with. Another way to read the 'stats'
function is this:
stats :: String -> String
stats str =
unwords [show . length . words $ str,
show . length . lines $ str,
show . length $ str]
Finally you can improve the command line argument processing itself
simply by being more sensible about what makes a valid command line:
main =
getArgs >>=
mapM_ (fmap stats . readFile >=> putStrLn)
Instead of expecting exactly one command line argument you print the
counts for every argument. That means, if there are no arguments, you
print no counts. This makes more sense than the highhanded "I want
exactly one argument, otherwise I won't work" syntax, because now your
whole program forms a homomorphism (shell syntax):
`prog x` `prog y` = `prog x y`
This allows reasoning and optimization.
Greets,
Ertugrul
Martin Drautzburg <[email protected]> wrote:
> in the code snippet below, is there a way to factor out the second
> "do"?
>
> import System (getArgs)
> main :: IO ()
> main = do
> args <- getArgs
> case args of
> [fname] -> do fstr <- readFile fname
> let nWords = length . words $ fstr
> nLines = length . lines $ fstr
> nChars = length fstr
> putStrLn . unwords $ [ show nLines
> , show nWords
> , show nChars
> , fname]
> _ ->putStrLn "usage: wc fname"
--
Not to be or to be and (not to be or to be and (not to be or to be and
(not to be or to be and ... that is the list monad.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20130127/f7505ede/attachment-0001.pgp>
------------------------------
Message: 3
Date: Sun, 27 Jan 2013 15:06:47 -0500
From: David McBride <[email protected]>
Subject: Re: [Haskell-beginners] How to unnest "do"
To: [email protected]
Message-ID:
<CAN+Tr40r+Y=rqa-phqnorbs0mzrh__rswbkyjbjfh_tovnu...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"
Here's what I would do. There's a MaybeT monad in the transormers library
that is pretty good for this sort of stuff. I might restructure it like
this:
module Main where
import Control.Monad.Trans.Maybe (runMaybeT, MaybeT)
import Control.Monad.Trans (liftIO)
import System.Environment (getArgs)
import Control.Applicative ((<|>))
margs :: MaybeT IO ()
margs = do
[fname] <- liftIO $ getArgs
fstr <- liftIO $ readFile fname
let nWords = length . words $ fstr
nLines = length . lines $ fstr
nChars = length fstr
liftIO . putStrLn . unwords $ [ show nLines, show nWords, show nChars]
mnoargs :: MaybeT IO ()
mnoargs = liftIO $ print "No args"
main = runMaybeT (margs <|> mnoargs)
This exploits the alternative instance of MaybeT. If the pattern match for
arguments fails, then the whole function returns nothing. That causes the
alternative to be run instead. Also since MaybeT has an instance for
MonadIO, you can do any IO you need by using liftIO.
There is also an EitherT type in the errors package that can return *why*
something failed, but I haven't messed with it a ton, so I can't really
give a tutorial.
On Sun, Jan 27, 2013 at 12:27 PM, Martin Drautzburg <
[email protected]> wrote:
> Hello all,
>
> in the code snippet below, is there a way to factor out the second "do"?
>
> import System (getArgs)
> main :: IO ()
> main = do
> args <- getArgs
> case args of
> [fname] -> do fstr <- readFile fname
> let nWords = length . words $ fstr
> nLines = length . lines $ fstr
> nChars = length fstr
> putStrLn . unwords $ [ show nLines
> , show nWords
> , show nChars
> , fname]
> _ ->putStrLn "usage: wc fname"
>
>
>
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20130127/8f9386f9/attachment-0001.htm>
------------------------------
Message: 4
Date: Sun, 27 Jan 2013 21:29:27 +0100
From: Emmanuel Touzery <[email protected]>
Subject: Re: [Haskell-beginners] How to unnest "do"
To: The Haskell-Beginners Mailing List - Discussion of primarily
beginner-level topics related to Haskell <[email protected]>
Message-ID:
<cac42renujn_m3eeltobbg0t38c2ytrbop9brkvqsrokbkzv...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"
> stats :: String -> String
> stats =
> unwords .
> sequence [show . length . words,
> show . length . lines,
> show . length]
>
>
[..]
> This improves the statistics code slightly, but uses some monadic
> machinery you may not be familiar with. Another way to read the 'stats'
> function is this:
>
> stats :: String -> String
> stats str =
> unwords [show . length . words $ str,
> show . length . lines $ str,
> show . length $ str]
>
I'm sorry, may I ask on which monad here is "sequence" operating?
I can see that sequence here turns [a->a] into a->[a], I'm just not sure
which is the monad at play here... I just need a little bit more
explanation about this code before I get it.
Thank you!
Emmanuel
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20130127/b50928dd/attachment-0001.htm>
------------------------------
Message: 5
Date: Sun, 27 Jan 2013 15:34:05 -0500
From: Brent Yorgey <[email protected]>
Subject: Re: [Haskell-beginners] How to unnest "do"
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii
On Sun, Jan 27, 2013 at 09:29:27PM +0100, Emmanuel Touzery wrote:
> > stats :: String -> String
> > stats =
> > unwords .
> > sequence [show . length . words,
> > show . length . lines,
> > show . length]
> >
> >
> [..]
>
>
> > This improves the statistics code slightly, but uses some monadic
> > machinery you may not be familiar with. Another way to read the 'stats'
> > function is this:
> >
> > stats :: String -> String
> > stats str =
> > unwords [show . length . words $ str,
> > show . length . lines $ str,
> > show . length $ str]
> >
>
>
> I'm sorry, may I ask on which monad here is "sequence" operating?
>
> I can see that sequence here turns [a->a] into a->[a], I'm just not sure
> which is the monad at play here... I just need a little bit more
> explanation about this code before I get it.
It is the ((->) a) monad, also known as the reader monad.
-Brent
------------------------------
Message: 6
Date: Sun, 27 Jan 2013 21:46:30 +0100
From: Emmanuel Touzery <[email protected]>
Subject: Re: [Haskell-beginners] How to unnest "do"
To: The Haskell-Beginners Mailing List - Discussion of primarily
beginner-level topics related to Haskell <[email protected]>
Message-ID:
<CAC42Rem0m+H_U-sc_PjmtJLp0+hk=f8mUk=zuodekxdbbt5...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"
Thank you. I thought it might be, but it isn't exactly intuitive for me at
this point. I'll read some more about that monad.
On 27 Jan 2013 21:35, "Brent Yorgey" <[email protected]> wrote:
> On Sun, Jan 27, 2013 at 09:29:27PM +0100, Emmanuel Touzery wrote:
> > > stats :: String -> String
> > > stats =
> > > unwords .
> > > sequence [show . length . words,
> > > show . length . lines,
> > > show . length]
> > >
> > >
> > [..]
> >
> >
> > > This improves the statistics code slightly, but uses some monadic
> > > machinery you may not be familiar with. Another way to read the
> 'stats'
> > > function is this:
> > >
> > > stats :: String -> String
> > > stats str =
> > > unwords [show . length . words $ str,
> > > show . length . lines $ str,
> > > show . length $ str]
> > >
> >
> >
> > I'm sorry, may I ask on which monad here is "sequence" operating?
> >
> > I can see that sequence here turns [a->a] into a->[a], I'm just not sure
> > which is the monad at play here... I just need a little bit more
> > explanation about this code before I get it.
>
> It is the ((->) a) monad, also known as the reader monad.
>
> -Brent
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20130127/52823779/attachment.htm>
------------------------------
_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners
End of Beginners Digest, Vol 55, Issue 30
*****************************************