This post is in response the blog entry IO doesn't Matter... and sort of boostraps this blog which I plan, for the time being, to use to write about learning Haskell. Learning Haskell seems to be what all the cool kids are doing these days or at least all the informed hackers.
I'm not going to address the blogger's semi-mystical claims. I think I can safely say my thoughts echo those of the 1st comment. This post is basically an attempt to elaborate on what I think would have been a better response to Me2's comment. Hell, I've been studying Haskell for the past two months and I had never heard of interact. I think it also warrants a discussion of some of the alternatives and pitfalls.
To start off, interact has the following type in Haskell:
interact :: (String -> String) -> IO ()
which basically says that interact takes a function as an argument (String -> String) and does IO, the "-> IO ()" part. In plain English, what it really does is take stdin as String and applies the function to it and writes the String to stdout. This makes writing the kind of *nix-style command tools that the author is talking about a breeze but it is not without its pitfalls.
So you can write up a program in Haskell like the following:
module Main
where
main = interact brains
brains :: String -> String
-- whatever you want the brains to be
and then you can compile it:
>ghc --make interact.hs -o tool
And use it:
>./tool < input > output
Just as you would the *nix tool, "wc".
There are some pitfalls. Let's say that we want brains to turn all of the characters to upper case:
brains :: String -> String
brains s = map Char.toUpper s
replacing the comment with our definition above and adding "import Char" just before main = ..., we can compile and run our program. If we don't pipe, we get something like this:
>./tool
hi
HI
hello
HELLO
cool, no? Why did I start out with SHOUTING instead of the canonical example, echo? Well, we can make brains do that:
brains s = "echo: " ++ s
We compile as before and run, tool:
>./tool
hi
echo: hi
hello
hello
What's up with that? Why doesn't hello have an "echo: " in front of it? It turns out that interact takes the entire stream from stdin to be the String passed to brains. While this worked when brains was turning everything into uppercase, it doesn't work for this problem. Luckily, there is an answer:
brains s = unlines $ map echo $ lines s
echo :: String -> String
echo s = "echo: " ++ s
Basically, lines s is one function application. It takes s and returns an array of Strings: lines :: String -> [String] using the return character, \n, as a delimiter. Because this is an array, we're going to apply the function echo to each element of the array using map. unlines, as the name suggests, takes an array of Strings and returns a single String with the return character, \n, as the delimiter.
(For those who don't know about $. Remember that function application binds from the left. Rather than mess everything up with parenthesization, we use the $ operator to make function application bind a less tightly and write things a bit more naturally).
If we compile this, we get what we wanted:
>./tool
hi
echo: hi
hello
echo: hello
We can make a bit of code more resusable if we do something like:
main = interact $ byLines brains
byLines :: (String -> String) -> String -> String
byLines f s = unlines $ map f $ lines s
brains s = "echo: " ++ s
What are the alternatives? Well, as someone pointed out in a different thread, Haskell is currently undergoing a Period of Monadic Enlightenment. Monads were basically invented to handle IO so the current idiom in Haskell is to use the IO Monad and the following pattern:
main = do
s <- getLine
if s /= ""
then do
putStr $ brains s
main
else return ()
This works just as well even if it is a bit more verbose. Why is it preferred? There seems to be some disagreement. One view is that Monads are more modular. Another is that interact was a hack for letting a purely functional language do IO and whose time has gone. Here is an interesting thread that discusses some of the issues.
Cheers!

4 comments:
For these kind of problems I often define 'io' as:
io f = interact (unlines . map f . lines)
main = io ("echo: " ++)
Pretty cute.
$ ghc -O T.hs -o T
$ ./T < T.hs
echo: io f = interact (unlines . map f . lines)
echo:
echo: main = io ("echo: " ++)
There's some examples of other unix tools written in this style here, http://haskell.org/haskellwiki/Simple_unix_tools
Wait, who says the verbose code is preferred style? April fool's day is not for quite a while yet.
Thanks for the nice post!
black mold exposureblack mold symptoms of exposurewrought iron garden gatesiron garden gates find them herefine thin hair hairstylessearch hair styles for fine thin hairnight vision binocularsbuy night vision binocularslipitor reactionslipitor allergic reactionsluxury beach resort in the philippines
afordable beach resorts in the philippineshomeopathy for eczema.baby eczema.save big with great mineral makeup bargainsmineral makeup wholesalersprodam iphone Apple prodam iphone prahacect iphone manualmanual for P 168 iphonefero 52 binocularsnight vision Fero 52 binocularsThe best night vision binoculars here
night vision binoculars bargainsfree photo albums computer programsfree software to make photo albumsfree tax formsprintable tax forms for free craftmatic air bedcraftmatic air bed adjustable info hereboyd air bedboyd night air bed lowest pricefind air beds in wisconsinbest air beds in wisconsincloud air beds
best cloud inflatable air bedssealy air beds portableportables air bedsrv luggage racksaluminum made rv luggage racksair bed raisedbest form raised air bedsaircraft support equipmentsbest support equipments for aircraftsbed air informercialsbest informercials bed airmattress sized air beds
bestair bed mattress antique doorknobsantique doorknob identification tipsdvd player troubleshootingtroubleshooting with the dvd playerflat panel television lcd vs plasmaflat panel lcd television versus plasma pic the bestThe causes of economic recessionwhat are the causes of economic recessionadjustable bed air foam The best bed air foam
hoof prints antique equestrian printsantique hoof prints equestrian printsBuy air bedadjustablebuy the best adjustable air bedsair beds canadian storesCanadian stores for air beds
migraine causemigraine treatments floridaflorida headache clinicdrying dessicantair drying dessicantdessicant air dryerpediatric asthmaasthma specialistasthma children specialistcarpet cleaning dallas txcarpet cleaners dallascarpet cleaning dallas
vero beach vacationvero beach vacationsbeach vacation homes veroms beach vacationsms beach vacationms beach condosmaui beach vacationmaui beach vacationsmaui beach clubbeach vacationsyour beach vacationscheap beach vacations
bob hairstylebob haircutsbob layeredpob hairstylebobbedclassic bobCare for Curly HairTips for Curly Haircurly hair12r 22.5 best pricetires truck bustires 12r 22.5
washington new housenew house houstonnew house san antonionew house venturanew houston house houston house tx
Post a Comment