Combining Monads

Dominic Steinitz dominic.steinitz@blueyonder.co.uk
Sat, 12 Apr 2003 21:52:32 +0100


Your program doesn't seem to have survived the transmission but try
http://www.cse.ogi.edu/~mpj/pubs/springschool.html or
http://www.cse.ogi.edu/~mpj/pubs/composing.html. For the theory, look at
Triples, Toposes and Theories by Barr & Wells. I think it's chapter 7 but I
haven't got it in front of me.

Dominic Steinitz
----- Original Message -----
From: <haskell-cafe-request@haskell.org>
To: <haskell-cafe@haskell.org>
Sent: Saturday, April 12, 2003 5:01 PM
Subject: Haskell-Cafe digest, Vol 1 #660 - 3 msgs


> Send Haskell-Cafe mailing list submissions to
> haskell-cafe@haskell.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
> http://www.haskell.org/mailman/listinfo/haskell-cafe
> or, via email, send a message with subject or body 'help' to
> haskell-cafe-request@haskell.org
>
> You can reach the person managing the list at
> haskell-cafe-admin@haskell.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Haskell-Cafe digest..."
>
>
> Today's Topics:
>
>    1. Combining monads (Mark T.B. Carroll)
>    2. Re: Combining monads (Scott Turner)
>    3. Re: Combining monads (Glynn Clements)
>
> --__--__--
>
> Message: 1
> Date: Sat, 12 Apr 2003 09:52:58 -0400 (EDT)
> From: "Mark T.B. Carroll" <Mark.Carroll@Aetion.com>
> To: haskell-cafe@haskell.org
> Subject: Combining monads
>
>   This message is in MIME format.  The first part should be readable text,
>   while the remaining parts are likely unreadable without MIME-aware
tools.
>   Send mail to mime@docserver.cac.washington.edu for more info.
>
> --481034957-302199926-1050155578=:555
> Content-Type: TEXT/PLAIN; charset=US-ASCII
>
> Hello! I am trying and failing to use one monad in another. A tiny example
> is enclosed, where I try to use IO to help along a State-ful computation.
> Is the real mistake in do_next? Is there a minimal rewrite that will get
> this working that I can use as a template for other things? Or, is there a
> good tutorial somewhere on this type of thing? Any pointers are much
> appreciated!
>
> -- Mark
>
> --481034957-302199926-1050155578=:555
> Content-Type: TEXT/PLAIN; charset=US-ASCII; name="Test.hs"
> Content-Transfer-Encoding: BASE64
> Content-ID: <Pine.LNX.4.44.0304120952580.555@cicero.aetion.internal>
> Content-Description: Example of incompetence
> Content-Disposition: attachment; filename="Test.hs"
>
> aW1wb3J0IENvbnRyb2wuTW9uYWQuU3RhdGUNCmltcG9ydCBEYXRhLkxpc3QN
> Cg0KZ2V0X2xlbmd0aCA6OiBTdHJpbmcgLT4gSU8gSW50DQoNCmdldF9sZW5n
> dGggbmFtZSA9IA0KICAgIGRvIGNvbnRlbnRzIDwtIHJlYWRGaWxlIG5hbWUN
> CiAgICAgICByZXR1cm4gKGxlbmd0aCAobGluZXMgY29udGVudHMpKQ0KDQp1
> cGRhdGVfYmVzdF93aXRoIDo6IChTdHJpbmcsIEludCkgLT4gU3RhdGVUIChT
> dHJpbmcsIEludCkgSU8gKCkNCg0KdXBkYXRlX2Jlc3Rfd2l0aCAoY3VycmVu
> dF9uYW1lLCBjdXJyZW50X2NvdW50KSA9DQogICAgZG8gKGJlc3RfbmFtZSwg
> YmVzdF9jb3VudCkgPC0gZ2V0DQogICAgICAgaWYgY3VycmVudF9jb3VudCA+
> IGJlc3RfY291bnQgDQoJICB0aGVuIHB1dCAoY3VycmVudF9uYW1lLCBjdXJy
> ZW50X2NvdW50KQ0KCSAgZWxzZSByZXR1cm4gKCkNCg0KZG9fbmV4dCA6OiBT
> dHJpbmcgLT4gU3RhdGVUIChTdHJpbmcsIEludCkgSU8gKCkNCg0KZG9fbmV4
> dCBuYW1lID0gDQogICAgZG8gY291bnQgPC0gZ2V0X2xlbmd0aCBuYW1lDQog
> ICAgICAgdXBkYXRlX2Jlc3Rfd2l0aCAobmFtZSwgY291bnQpDQoNCmxvbmdl
> c3RfZmlsZSA6OiBbU3RyaW5nXSAtPiBJTyAoU3RyaW5nLCBJbnQpDQoNCmxv
> bmdlc3RfZmlsZSBuYW1lcyA9DQogICAgZXhlY1N0YXRlVCAoc2VxdWVuY2Vf
> IChtYXAgZG9fbmV4dCBuYW1lcykpICgibm9uZSIsIDApDQoNCm1haW4gPSBk
> byAobmFtZSwgY291bnQpIDwtIGxvbmdlc3RfZmlsZSBbIi9ldGMvaG9zdG5h
> bWUiLCAiL2V0Yy9udHAuY29uZiIsICIvZXRjL3RpbWV6b25lIl0NCgkgIHB1
> dFN0ckxuICgiTG9uZ2VzdCBmaWxlIGlzICIgKysgbmFtZSArKyAiIHdoaWNo
> IGlzICIgKysgc2hvdyBjb3VudCArKyAiIGxpbmVzIGxvbmciKQ0K
> --481034957-302199926-1050155578=:555--
>
> --__--__--
>
> Message: 2
> From: Scott Turner <p.turner@computer.org>
> To: "Mark T.B. Carroll" <Mark.Carroll@Aetion.com>,
haskell-cafe@haskell.org
> Subject: Re: Combining monads
> Date: Sat, 12 Apr 2003 09:14:45 -0500
>
> On Saturday 12 April 2003 09:52, Mark T.B. Carroll wrote:
> > Hello! I am trying and failing to use one monad in another.
> > Is there a minimal rewrite that will get this working ... ?
> Yes. Just add lift.
>      do count <- lift $ get_length name
>
>
> --__--__--
>
> Message: 3
> From: Glynn Clements <glynn.clements@virgin.net>
> Date: Sat, 12 Apr 2003 15:26:03 +0100
> To: "Mark T.B. Carroll" <Mark.Carroll@Aetion.com>
> Cc: haskell-cafe@haskell.org
> Subject: Re: Combining monads
>
>
> Mark T.B. Carroll wrote:
>
> > Hello! I am trying and failing to use one monad in another. A tiny
example
> > is enclosed, where I try to use IO to help along a State-ful
computation.
> > Is the real mistake in do_next? Is there a minimal rewrite that will get
> > this working that I can use as a template for other things? Or, is there
a
> > good tutorial somewhere on this type of thing? Any pointers are much
> > appreciated!
>
> Combining monads isn't straightforward. There is a paper on the topic,
> at:
>
>
http://cm.bell-labs.com/cm/cs/who/wadler/topics/monads.html#combining-monads
>
> However, you can't really combine the IO monad in the way that the
> above paper describes.
>
> The most direct way to fix your program is to use an IORef instead of
> a state monad, e.g.
>
> > import IORef
>
> > update_best_with :: IORef (String, Int) -> (String, Int) -> IO ()
> > update_best_with ref (current_name, current_count) = do
> > (best_name, best_count) <- readIORef ref
> > when (current_count > best_count) $ do
> > writeIORef ref (current_name, current_count)
>
> > do_next :: IORef (String, Int) -> String -> IO ()
> > do_next ref name = do
> > count <- get_length name
> > update_best_with ref (name, count)
>
> > longest_file :: [String] -> IO (String, Int)
> > longest_file names = do
> > ref <- newIORef ("none", 0)
> > mapM_ (do_next ref) names
> > readIORef ref
>
> A more elegant solution would be to generate a list of filename/length
> pairs (e.g. using mapM), then just use maximumBy to select the
> longest, e.g.
>
> > get_length' :: String -> IO (String, Int)
> > get_length' name = do
> > length <- get_length name
> > return (name, length)
>
> > longest_file :: [String] -> IO (String, Int)
> > longest_file names = do
> > pairs <- mapM get_length' names
> > return $ maximumBy cmp pairs
> > where cmp (_, l1) (_, l2) = compare l1 l2
>
> --
> Glynn Clements <glynn.clements@virgin.net>
>
>
> --__--__--
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>
> End of Haskell-Cafe Digest