https://wiki.haskell.org/api.php?action=feedcontributions&user=Mvanier&feedformat=atomHaskellWiki - User contributions [en]2021-03-01T07:37:10ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Blog_articles/Monads&diff=38374Blog articles/Monads2011-01-28T01:44:59Z<p>Mvanier: Added a link.</p>
<hr />
<div>== Monads ==<br />
<br />
* [http://cale.yi.org/index.php/The_Monad_Laws The monad laws]<br />
* [http://sigfpe.blogspot.com/2007/04/trivial-monad.html The Trivial Monad]<br />
* [http://sigfpe.blogspot.com/2007/04/homeland-security-threat-level-monad.html Tracking tainted data: Homeland Security Threat Level Monad]<br />
* [http://sigfpe.blogspot.com/2006/10/monads-field-guide.html Monads: a field guide]<br />
* [http://sigfpe.blogspot.com/2006/11/variable-substitution-gives.html Variable substitution gives a ... monad]<br />
* [http://sigfpe.blogspot.com/2007/01/monads-hidden-behind-every-zipper.html The monad behind every zipper]<br />
* [http://sigfpe.blogspot.com/2007/02/monads-for-vector-spaces-probability.html Monads for vector spaces, probability and quantum mechanics pt. I]<br />
* [http://sigfpe.wordpress.com/2007/03/04/monads-vector-spaces-and-quantum-mechanics-pt-ii/ Monads, Vector Spaces and Quantum Mechanics pt. II]<br />
* [http://sigfpe.blogspot.com/2007/06/how-to-write-tolerably-efficient.html How to write tolerably efficient optimzation code without really trying...]<br />
* [http://sigfpe.blogspot.com/2007/06/monads-from-algebra-and-the-gray-code.html Monads from Algebra and the the Gray Code from Groups]<br />
* [http://sigfpe.blogspot.com/2006/06/monads-kleisli-arrows-comonads-and.html Monads, Kleisli Arrows, Comonads and other Rambling Thoughts]<br />
* [http://sigfpe.blogspot.com/2007/11/io-monad-for-people-who-simply-dont.html The IO Monad for People who Simply Don't Care]<br />
* [http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/11#interpreters-with-reader-monads Quick interpreters with the Reader monad]<br />
* [http://hierodule.livejournal.com/69052.html Monads]<br />
* [http://neilbartlett.name/blog/?p=13 More on Haskell, Side Effects and Code Reuse]<br />
* [http://scienceblogs.com/goodmath/2007/01/haskell_a_first_step_into_mona_1.php A First Step Into Monads]<br />
* [http://scienceblogs.com/goodmath/2007/01/more_monads_stateful_programmi_1.php More Monads: Stateful Programming]<br />
* [http://scienceblogs.com/goodmath/2007/01/the_theory_of_monads_and_the_m_1.php The theory of monads]<br />
* [http://www.alpheccar.org/en/posts/show/60 A newbie in Haskell land or another monad tutorial]<br />
* [http://www.alpheccar.org/en/posts/show/61 A newbie in Haskell land : The (->) monad]<br />
* [http://www.randomhacks.net/articles/2007/03/03/smart-classification-with-haskell Smart classification using Bayesian monads]<br />
* [http://www.randomhacks.net/articles/2007/03/05/three-things-i-dont-understand-about-monads 3 open problems with monads]<br />
* [http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes Monads in 15 minutes: Backtracking and Maybe]<br />
* [http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros How to make Data.Set a monad]<br />
* [http://www.sdowney.org/2007/01/monads-rest-and-c-template.html Monads work because they have a tight interface]<br />
* [http://www.serpentine.com/blog/2007/01/09/haskell-bootstrapping-into-a-clue-about-monads/ Haskell: bootstrapping into a clue about monads]<br />
* [http://www.rfc1149.net/blog/2007/03/06/why-monads-matter/#more-110 Why monads matter]<br />
* [http://www.bolour.com/papers/monads-through-pictures.html Monads through Pictures]<br />
* [http://gelisam.blogspot.com/2006/10/monads-as-universe-helpers.html Monads as universe helpers]<br />
* [http://therning.org/magnus/archives/215 Simple state monad]<br />
* [http://therning.org/magnus/archives/269 repeat and sequence]<br />
* [http://lukeplant.me.uk/blog.php?id=1107301659 What's a monad?]<br />
* [http://comonad.com/reader/2007/parameterized-monads-in-haskell/ Parameterized Monads in Haskell]<br />
* [http://ahamsandwich.wordpress.com/2007/07/26/monads-and-why-monad-tutorials-are-all-awful/ Monads! (and Why Monad Tutorials Are All Awful)]<br />
* [http://www.haskell.org/haskellwiki/Monads_as_computation Monads as computation]<br />
* [http://davblog48.blogspot.com/2007/08/monads-are-hard-to-teach.html Monads are hard to teach]<br />
* [http://luqui.org/blog/archives/2007/08/05/haskell-state-accessors-second-attempt-composability/ Haskell State Accessors (second attempt: Composability)]<br />
* [http://www.bofh.org.uk/articles/2007/08/07/monads Beginning with monads]<br />
* [http://dailykibitz.blogspot.com/2007/08/learning-about-computational-monads.html Learning about (Computational) Monads ]<br />
* [http://osteele.com/archives/2007/12/overloading-semicolon Overloading Semicolon, or, monads from 10,000 Feet]<br />
* [http://mvanier.livejournal.com/3917.html Yet Another Monad Tutorial]<br />
<br />
== Monad transformers ==<br />
<br />
* [http://conway.rutgers.edu/~ccshan/wiki/blog/posts/Monad_transformers.html A twisted history of monad transformers]<br />
* [http://cale.yi.org/index.php/How_To_Use_Monad_Transformers How To Use Monad Transformers]<br />
* [http://sigfpe.blogspot.com/2006/09/local-and-global-side-effects-with.html Local and global side effects with monad transformers]<br />
* [http://sigfpe.blogspot.com/2006/05/grok-haskell-monad-transformers.html Grok monad transformers]<br />
* [http://scsibug.com/2006/11/28/a-simple-game-with-statet/ A Simple Game with StateT]<br />
<br />
=== Continuation monads ===<br />
<br />
* [http://therning.org/magnus/archives/306 Continuing with Continuations]<br />
<br />
== Arrows ==<br />
<br />
* [http://kpreid.livejournal.com/7351.html Concatenative programming in Haskell's Arrows]<br />
* [http://abstractabsurd.blogspot.com/2007/04/arrows-security.html Arrows and security]<br />
* [http://cgi.cse.unsw.edu.au/~dons/blog/2007/07/31 Run length encoding in Haskell]<br />
* [http://neilbartlett.name/blog/2007/08/01/haskell-explaining-arrows-through-xml-transformationa/ Haskell: Explaining Arrows through XML Transformations]<br />
* [http://www.drmaciver.com/2007/08/playing-with-arrows/ Playing with Arrows]<br />
* [http://onthebalcony.wordpress.com/2007/02/19/my-evolution-as-a-haskell-programmer/ My Evolution as a Haskell Programmer: Factorial with Arrows]<br />
* [http://monadicheadaches.blogspot.com/2007/12/arrows-first-encounter.html Arrows first encounter]<br />
<br />
== Comonads ==<br />
<br />
* [http://sigfpe.blogspot.com/2007/02/comonads-and-reading-from-future.html Comonads and reading from the future]<br />
* [http://sigfpe.blogspot.com/2006/12/evaluating-cellular-automata-is.html Evaluating cellular automata is co-monadic]<br />
* [http://gelisam.blogspot.com/2007/04/i-understand-comonads.html Understanding comonads]<br />
<br />
== Applicative Functors ==<br />
<br />
Nobody has written blog articles on applicative functors - so how about a functional pearl:<br />
<br />
* [http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf Applicative Programming with Effects]<br />
<br />
== Further reading ==<br />
<br />
* [http://haskell.org/haskellwiki/Research_papers/Monads_and_arrows Research papers on monads, comonads and arrows]<br />
* [http://haskell.org/haskellwiki/Category:Monad Wiki articles about monads]<br />
* [http://en.wikibooks.org/wiki/Haskell/Understanding_monads Understanding monads]<br />
* [http://en.wikibooks.org/wiki/Haskell/Advanced_monads Advanced monads]<br />
* [http://en.wikibooks.org/wiki/Haskell/Monad_transformers Monad transformers]</div>Mvanierhttps://wiki.haskell.org/index.php?title=Monad_tutorials_timeline&diff=36720Monad tutorials timeline2010-09-08T20:40:07Z<p>Mvanier: </p>
<hr />
<div>[[Category:History]]<br />
[[Category:Monad]]<br />
[[Category:Tutorials]]<br />
<br />
This timeline covers not just monad tutorials, but interesting events in monad tutorial history. Please update this list! Don't worry about getting dates, authors, blurbs unless you really want to. We can fix it later.<br />
<br />
Older tutorials are especially interesting.<br />
<br />
== before 2000 ==<br />
<br />
* 1992-08 [http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf Monads for Functional Programming] - Phil Wadler<br />
*: "Shall I be pure or impure?" One of the earliest papers on monads by the man hiself. Has been called the "''ne plus ultra'' of approachable, useful introductions to monads". It's pretty hefty (31 pages), which is a good thing!<br />
* 1999-02 [http://www-users.mat.uni.torun.pl/~fly/materialy/fp/haskell-doc/Monads.html What the hell are Monads?] Noel Winstanley<br />
*: Written when 'what is a monad' started becoming an FAQ. Very short and sweet, advertised as more examples than theory. "Once upon a time, people wrote their Haskell programs by sequencing together operations in an ad-hoc way."<br />
* 1999-Spring [http://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm Monads for the working Haskell Programmer] - Theodore S. Norvell<br />
*: One of the original tutorials, originally written for Gofer and eventually "updated for Haskell98"<br />
<br />
== year 2002 ==<br />
<br />
* 2002 [http://en.wikibooks.org/wiki/Haskell/YAHT Yet Another Haskell Tutorial] - Hal Daumé III<br />
*: The most recommended Haskell tutorial ever. Not a monad tutorial per se, but it does address the topic<br />
<br />
== year 2003 ==<br />
<br />
* 2003-08 [http://www.haskell.org/all_about_monads/html/ All about Monads] - Jeff Newbern<br />
*: A comprehensive introduction to monads, covering also "advanced" topics like monad transformers and use of some common monads. There is an appendix which presents monads as assembly lines.<br />
<br />
== year 2004 ==<br />
<br />
* 2004-07 [http://www.ccs.neu.edu/home/dherman/research/tutorials/monads-for-schemers.txt A Schemer's Introduction to Monads]<br />
*: "This will be an introduction to monads from a Lisp/Scheme perspective, with the assumption that the reader is comfortable with continuations, CPS, accumulators, and accumulator-passing style."<br />
* 2004-07 [[Monads as Containers]] - Cale Gibbard<br />
*: Presents monads as boxes. Uses <hask>fmap</hask> and <hask>join</hask>. "If you will give me a blueberry for each apple I give you <hask>(a -> b)</hask>, and I have a box of apples <hask>(f a)</hask>, then I can get a box of blueberries <hask>(f b)</hask>."<br />
* 2004-08 [http://sleepingsquirrel.org/monads/monads.html Monads in Perl] - Greg Buchholz<br />
*: Written in the spirit of TMTOWTDI<br />
<br />
== year 2005 ==<br />
<br />
* 2005-07 [http://moonbase.rydia.net/mental/writings/programming/monads-in-ruby/00introduction.html Monads in Ruby] - MenTaLguY<br />
*: Presents monads in a friendly language, starting from Identity and building on up<br />
* 2005-11 [http://www.loria.fr/~kow/monads Of monads and space suits] - Eric Kow<br />
*: Functions are space stations, parameters are astronauts and monads are space suits that let us safely travel from one function to another.<br />
<br />
== year 2006 ==<br />
<br />
* 2006-03 [http://en.wikibooks.org/w/index.php?title=Haskell/Understanding_monads&oldid=933545 Understanding Monads] - Eric Kow<br />
*: Monads as nuclear waste containers, an adaptation of monads as space suits with a new metaphor suggested by Paul Johnson<br />
* 2006-07 [[The Monadic Way]] - Andrea Rossato<br />
*: A two-part tutorial. The first part shows you how build a simple evaluator, and the second part shows you how to "take the complexity" out of it by using techniques such as monad transformers<br />
* 2006-08 [http://sigfpe.blogspot.com/2006/08/you-could-have-invented-monads-and.html You could have invented monads! (and maybe you already have)] - Dan Piponi<br />
*: "Writing introductions to monads seems to have developed into an industry," Dan (sigfpe) observes. He argues that monads are not "something esoteric in need of explanation", but walks you through the process of reinventing monads to solve some very basic and practical problems.<br />
* 2006-09 [[Meet Bob The Monadic Lover]] - Andrea Rossato<br />
*: Bob embarks upon a series of romantic conquests... bind bind bind, Paula, Luisa, Antonia<br />
* 2006-10 [http://www.grabmueller.de/martin/www/pub/Transformers.en.html Monad Transformers Step by Step] - Martin Grabmüller<br />
** Monad transformers are rarely covered in introductory tutorials. This "is not a paper about implementing transformers, but about using them to write elegant, clean and powerful programs in Haskell". Available as a 12 page PDF or .lhs file.<br />
* 2006-11 [http://www.haskell.org/pipermail/haskell-cafe/2006-November/019190.html There's a Monster in my Haskell!] Andrew Pimlott<br />
*: This delightful "tutorial" presents monads as monsters which devour values, use them to feed other monsters and regurgitate them when slain.<br />
* 2006-12 [http://blog.tmorris.net/maybe-monad-in-java/ Maybe Monad in Java] - Tony Morris<br />
*: Monads can also be useful in Java!<br />
<br />
== year 2007 ==<br />
<br />
* 2007-01 [http://koweycode.blogspot.com/2007/01/think-of-monad.html Think of a monad] - Don Stewart (reposted on Eric Kow's blog)<br />
*: Don integrates some pre-existing monadic metaphors, shedding light on monads in a truly comprehensive manner (illustration by Eric)<br />
* 2007-02 [http://kawagner.blogspot.com/2007/02/understanding-monads-for-real.html Understanding Monads. For Real] - Karsten Wagner<br />
*: A monad is like a macro<br />
* 2007-02 [http://patryshev.com/monad/m-intro.html Crash Course in Monads] Monads for Mathematicians<br />
*:Author's Description: This crash course starts with an EASY! introduction to categories and functors, then we define a monad, then give some basic examples of monads in categories, then present monadic terminology as used in programming languages.<br />
*: Then I lie down in a dark room with a warm wet cloth over my eyes.<br />
* 2007-04 [http://saxophone.jpberlin.de/MonadTransformer?source=http%3A%2F%2Fwww%2Ehaskell%2Eorg%2Fhaskellwiki%2FCategory%3AMonad&language=English The Real Monad Transformer] - Henning Thielemann<br />
*: Not a tutorial either, but an important aid in demystifying monads<br />
* 2007-03 [http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes Monads in 15 Minutes] - Eric Kidd<br />
*: Eric boils monads down to 15 minutes, using backtracking and Maybe as motivating examples. Eric uses <hask>join</hask>, which seems quite rare for monad tutorials (cf Cale's ''Monads as containers'')<br />
* 2007-07 [http://ahamsandwich.wordpress.com/2007/07/26/monads-and-why-monad-tutorials-are-all-awful/ Monads! (and why monad tutorials are all awful)] - Colin Gordon?<br />
*: Csgordon reports that monad tutorials tend to "get horribly botched" and says "[they] either bored me to tears, struck me as completely inane, or simply confused me". He uncovers the early Phil Wadler's paper, ''Monads for Functional Programming'', which not only gives a clear explanation but provides ''non-trivial'' motivating examples<br />
* 2007-08 [[Monads as computation]] - Cale Gibbard<br />
*: A very straightforward presentation of monads. Notable for its "The whole point" section, which conveys why we bother with all this monad business.<br />
* 2007-08 [http://en.wikibooks.org/wiki/Haskell/Understanding%20monads Understanding Monads] (2) - Apfelmus<br />
*: Wikibook rewrite of the original monads tutorial. Less fluff, more pedagogy. [In progress at the time of this writing].<br />
* 2007-08 [[Monad (sans metaphors)]] - Claus Reinke<br />
*: From a discussion about monad tutorials on Haskell Café (the name is due to haskellwiki user 'Green tea').<br />
<br />
== year 2008 ==<br />
* 2008-06 [http://spbhug.folding-maps.org/wiki/Monads Monads] (in Russian) and [http://spbhug.folding-maps.org/wiki/MonadsEn Monads] (in English) - Yet another monad tutorial, by Eugene Kirpichov; fairly advanced but skips monad transformers. Oriented towards a broader understanding of monads than just IO and Maybe.<br />
<br />
== year 2009 ==<br />
* 2009-01 [http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/ Abstraction, intuition, and the “monad tutorial fallacy”] Not a monad tutorial itself, but a comment on monad tutorials and why many of them are so unhelpful.<br />
<br />
* 2009-03 [http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/ A Monad Tutorial for Clojure Programmers] An interesting perspective on monads .<br />
<br />
* 2009-11 [[What a Monad is not]] A desperate attempt to end the eternal chain of monad tutorials<br />
<br />
== year 2010 ==<br />
* 2010-07 [https://intoverflow.wordpress.com/2010/07/20/i-come-from-java-and-want-to-know-what-monads-are-in-haskell/ I come from Java and want to know what monads are in Haskell] - Tim Carstens<br />
*: An example showing how a simple Java class is translated into a stack of monad transformers, with a metaphor about how monads are like conversations, and why this idea should be familiar to OO programmers.<br />
<br />
* 2010-08 [http://learnyouahaskell.com/a-fistful-of-monads A Fistful of Monads] from Learn You a Haskell<br />
*: An introduction to monads that builds on applicative functors<br />
<br />
* 2010-08 [http://mvanier.livejournal.com/3917.html Yet Another Monad Tutorial]<br />
*: An ongoing sequence of extremely detailed tutorials deriving monads from first principles.</div>Mvanierhttps://wiki.haskell.org/index.php?title=Monad_tutorials_timeline&diff=36716Monad tutorials timeline2010-09-08T18:21:27Z<p>Mvanier: </p>
<hr />
<div>[[Category:History]]<br />
[[Category:Monad]]<br />
[[Category:Tutorials]]<br />
<br />
This timeline covers not just monad tutorials, but interesting events in monad tutorial history. Please update this list! Don't worry about getting dates, authors, blurbs unless you really want to. We can fix it later.<br />
<br />
Older tutorials are especially interesting.<br />
<br />
== before 2000 ==<br />
<br />
* 1992-08 [http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf Monads for Functional Programming] - Phil Wadler<br />
*: "Shall I be pure or impure?" One of the earliest papers on monads by the man hiself. Has been called the "''ne plus ultra'' of approachable, useful introductions to monads". It's pretty hefty (31 pages), which is a good thing!<br />
* 1999-02 [http://www-users.mat.uni.torun.pl/~fly/materialy/fp/haskell-doc/Monads.html What the hell are Monads?] Noel Winstanley<br />
*: Written when 'what is a monad' started becoming an FAQ. Very short and sweet, advertised as more examples than theory. "Once upon a time, people wrote their Haskell programs by sequencing together operations in an ad-hoc way."<br />
* 1999-Spring [http://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm Monads for the working Haskell Programmer] - Theodore S. Norvell<br />
*: One of the original tutorials, originally written for Gofer and eventually "updated for Haskell98"<br />
<br />
== year 2002 ==<br />
<br />
* 2002 [http://en.wikibooks.org/wiki/Haskell/YAHT Yet Another Haskell Tutorial] - Hal Daumé III<br />
*: The most recommended Haskell tutorial ever. Not a monad tutorial per se, but it does address the topic<br />
<br />
== year 2003 ==<br />
<br />
* 2003-08 [http://www.haskell.org/all_about_monads/html/ All about Monads] - Jeff Newbern<br />
*: A comprehensive introduction to monads, covering also "advanced" topics like monad transformers and use of some common monads. There is an appendix which presents monads as assembly lines.<br />
<br />
== year 2004 ==<br />
<br />
* 2004-07 [http://www.ccs.neu.edu/home/dherman/research/tutorials/monads-for-schemers.txt A Schemer's Introduction to Monads]<br />
*: "This will be an introduction to monads from a Lisp/Scheme perspective, with the assumption that the reader is comfortable with continuations, CPS, accumulators, and accumulator-passing style."<br />
* 2004-07 [[Monads as Containers]] - Cale Gibbard<br />
*: Presents monads as boxes. Uses <hask>fmap</hask> and <hask>join</hask>. "If you will give me a blueberry for each apple I give you <hask>(a -> b)</hask>, and I have a box of apples <hask>(f a)</hask>, then I can get a box of blueberries <hask>(f b)</hask>."<br />
* 2004-08 [http://sleepingsquirrel.org/monads/monads.html Monads in Perl] - Greg Buchholz<br />
*: Written in the spirit of TMTOWTDI<br />
<br />
== year 2005 ==<br />
<br />
* 2005-07 [http://moonbase.rydia.net/mental/writings/programming/monads-in-ruby/00introduction.html Monads in Ruby] - MenTaLguY<br />
*: Presents monads in a friendly language, starting from Identity and building on up<br />
* 2005-11 [http://www.loria.fr/~kow/monads Of monads and space suits] - Eric Kow<br />
*: Functions are space stations, parameters are astronauts and monads are space suits that let us safely travel from one function to another.<br />
<br />
== year 2006 ==<br />
<br />
* 2006-03 [http://en.wikibooks.org/w/index.php?title=Haskell/Understanding_monads&oldid=933545 Understanding Monads] - Eric Kow<br />
*: Monads as nuclear waste containers, an adaptation of monads as space suits with a new metaphor suggested by Paul Johnson<br />
* 2006-07 [[The Monadic Way]] - Andrea Rossato<br />
*: A two-part tutorial. The first part shows you how build a simple evaluator, and the second part shows you how to "take the complexity" out of it by using techniques such as monad transformers<br />
* 2006-08 [http://sigfpe.blogspot.com/2006/08/you-could-have-invented-monads-and.html You could have invented monads! (and maybe you already have)] - Dan Piponi<br />
*: "Writing introductions to monads seems to have developed into an industry," Dan (sigfpe) observes. He argues that monads are not "something esoteric in need of explanation", but walks you through the process of reinventing monads to solve some very basic and practical problems.<br />
* 2006-09 [[Meet Bob The Monadic Lover]] - Andrea Rossato<br />
*: Bob embarks upon a series of romantic conquests... bind bind bind, Paula, Luisa, Antonia<br />
* 2006-10 [http://www.grabmueller.de/martin/www/pub/Transformers.en.html Monad Transformers Step by Step] - Martin Grabmüller<br />
** Monad transformers are rarely covered in introductory tutorials. This "is not a paper about implementing transformers, but about using them to write elegant, clean and powerful programs in Haskell". Available as a 12 page PDF or .lhs file.<br />
* 2006-11 [http://www.haskell.org/pipermail/haskell-cafe/2006-November/019190.html There's a Monster in my Haskell!] Andrew Pimlott<br />
*: This delightful "tutorial" presents monads as monsters which devour values, use them to feed other monsters and regurgitate them when slain.<br />
* 2006-12 [http://blog.tmorris.net/maybe-monad-in-java/ Maybe Monad in Java] - Tony Morris<br />
*: Monads can also be useful in Java!<br />
<br />
== year 2007 ==<br />
<br />
* 2007-01 [http://koweycode.blogspot.com/2007/01/think-of-monad.html Think of a monad] - Don Stewart (reposted on Eric Kow's blog)<br />
*: Don integrates some pre-existing monadic metaphors, shedding light on monads in a truly comprehensive manner (illustration by Eric)<br />
* 2007-02 [http://kawagner.blogspot.com/2007/02/understanding-monads-for-real.html Understanding Monads. For Real] - Karsten Wagner<br />
*: A monad is like a macro<br />
* 2007-02 [http://patryshev.com/monad/m-intro.html Crash Course in Monads] Monads for Mathematicians<br />
*:Author's Description: This crash course starts with an EASY! introduction to categories and functors, then we define a monad, then give some basic examples of monads in categories, then present monadic terminology as used in programming languages.<br />
*: Then I lie down in a dark room with a warm wet cloth over my eyes.<br />
* 2007-04 [http://saxophone.jpberlin.de/MonadTransformer?source=http%3A%2F%2Fwww%2Ehaskell%2Eorg%2Fhaskellwiki%2FCategory%3AMonad&language=English The Real Monad Transformer] - Henning Thielemann<br />
*: Not a tutorial either, but an important aid in demystifying monads<br />
* 2007-03 [http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes Monads in 15 Minutes] - Eric Kidd<br />
*: Eric boils monads down to 15 minutes, using backtracking and Maybe as motivating examples. Eric uses <hask>join</hask>, which seems quite rare for monad tutorials (cf Cale's ''Monads as containers'')<br />
* 2007-07 [http://ahamsandwich.wordpress.com/2007/07/26/monads-and-why-monad-tutorials-are-all-awful/ Monads! (and why monad tutorials are all awful)] - Colin Gordon?<br />
*: Csgordon reports that monad tutorials tend to "get horribly botched" and says "[they] either bored me to tears, struck me as completely inane, or simply confused me". He uncovers the early Phil Wadler's paper, ''Monads for Functional Programming'', which not only gives a clear explanation but provides ''non-trivial'' motivating examples<br />
* 2007-08 [[Monads as computation]] - Cale Gibbard<br />
*: A very straightforward presentation of monads. Notable for its "The whole point" section, which conveys why we bother with all this monad business.<br />
* 2007-08 [http://en.wikibooks.org/wiki/Haskell/Understanding%20monads Understanding Monads] (2) - Apfelmus<br />
*: Wikibook rewrite of the original monads tutorial. Less fluff, more pedagogy. [In progress at the time of this writing].<br />
* 2007-08 [[Monad (sans metaphors)]] - Claus Reinke<br />
*: From a discussion about monad tutorials on Haskell Café (the name is due to haskellwiki user 'Green tea').<br />
<br />
== year 2008 ==<br />
* 2008-06 [http://spbhug.folding-maps.org/wiki/Monads Monads] (in Russian) and [http://spbhug.folding-maps.org/wiki/MonadsEn Monads] (in English) - Yet another monad tutorial, by Eugene Kirpichov; fairly advanced but skips monad transformers. Oriented towards a broader understanding of monads than just IO and Maybe.<br />
<br />
== year 2009 ==<br />
* 2009-01 [http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/ Abstraction, intuition, and the “monad tutorial fallacy”] Not a monad tutorial itself, but a comment on monad tutorials and why many of them are so unhelpful.<br />
<br />
* 2009-03 [http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/ A Monad Tutorial for Clojure Programmers] An interesting perspective on monads .<br />
<br />
* 2009-11 [[What a Monad is not]] A desperate attempt to end the eternal chain of monad tutorials<br />
<br />
== year 2010 ==<br />
* 2010-07 [https://intoverflow.wordpress.com/2010/07/20/i-come-from-java-and-want-to-know-what-monads-are-in-haskell/ I come from Java and want to know what monads are in Haskell] - Tim Carstens<br />
*: An example showing how a simple Java class is translated into a stack of monad transformers, with a metaphor about how monads are like conversations, and why this idea should be familiar to OO programmers.<br />
<br />
* 2010-08 [http://learnyouahaskell.com/a-fistful-of-monads A Fistful of Monads] from Learn You a Haskell<br />
*: An introduction to monads that builds on applicative functors<br />
<br />
* 2010-08 [http://mvanier.livejournal.com/3917.html Yet Another Monad Tutorial]<br />
*: First in an ongoing sequence of extremely detailed tutorials deriving monads from first principles.</div>Mvanierhttps://wiki.haskell.org/index.php?title=Simonpj/Talk:FunWithTypeFuns&diff=28836Simonpj/Talk:FunWithTypeFuns2009-07-03T03:14:08Z<p>Mvanier: </p>
<hr />
<div>= Fun with Type Functions =<br />
<br />
Here is Version 2 of our paper:<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/typefun.pdf Fun With Type Functions (version 2)]''', Oleg Kiselyov, Ken Shan, and Simon Peyton Jones<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/FunWithTypeFuns-Apr09.pdf Slides (PDF)]'''<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs Source code]'''<br />
<br />
which will appear in the proceedings of Tony Hoare's 75th birthday celebration.<br />
<blockquote><br />
'''Abstract'''. Tony Hoare has always been a leader in writing down and proving<br />
properties of programs. To prove properties of programs automatically,<br />
the most widely used technology today is by far the ubiquitous type checker.<br />
Alas, static type systems inevitably exclude some good programs<br />
and allow some bad ones. This dilemma motivates us to describe some fun we've<br />
been having with Haskell, by making the type system more expressive<br />
without losing the benefits of automatic proof and compact expression.<br />
<p><br />
Haskell's type system extends Hindley-Milner with two distinctive<br />
features: polymorphism over type constructors and overloading<br />
using type classes. These features have been integral to Haskell<br />
since its beginning, and they are widely used and appreciated. More recently, Haskell has been enriched with<br />
''type families'', or ''associated types'', <br />
which allows functions on types to be<br />
expressed as straightforwardly as functions on values. This facility<br />
makes it easier for programmers to effectively extend the compiler by<br />
writing functional programs that execute during type-checking.<br />
</p><p><br />
This paper gives a programmer's tour of type families as they are<br />
supported in GHC today.<br />
</p></blockquote><br />
<br />
This Wiki page is a discussion page for the paper. If you are kind enough to read this paper, please help us by jotting down any thoughts it triggers off. Things to think about:<br />
* What is unclear?<br />
* What is omitted that you'd like to see?<br />
* Do you have any cool examples that are of a somewhat different character than the ones we describe? (If so, do explain the example on this page!)<br />
<br />
You can identify your entries by preceding them with four tildes. Doing so adds your name, and the date. Thus:<br />
<br />
:[[User:Simonpj|Simonpj]] 08:42, 19 April 2007 (UTC) Note from Simon<br />
<br />
If you say who you are in this way, we'll be able to acknowledge your help in a revised version of the paper.<br />
<br />
------------------------<br />
Add comments here (newest at the top):<br />
<br />
[[User:Mvanier|Mvanier]] 03:14, 3 July 2009 (UTC) The source code link seems to be dead.<br />
<br />
<br />
-------------------------<br />
'''Stuff below here refers to [http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/typefun-v1.pdf Version 1 of the paper], now retired.'''<br />
-------------------------<br />
<br />
[[User:Oleg|Oleg]] 02:55, 3 June 2009 (UTC) <br />
<br />
Thank you indeed for all the comments and suggestions!<br />
<br />
i have dealt with all the comments and fixed all the noted problems. I<br />
have a few questions about several suggestions though. I should remark<br />
first that the complete code discussed in the paper is available,<br />
presently in our darcs repository. I guess Simon has not decided of a<br />
site to host the online version of the paper with the Appendices and<br />
the code. Incidentally, code fragments in the paper are lifted<br />
straight from the working code, using the remarkably useful<br />
\VerbatimInput.<br />
<br />
--------------------------------------<br />
<br />
[[User:Byorgey|Byorgey]] 20:07, 19 May 2009 (UTC) <br />
* p. 32:<br />
** "powerful, but the" -> "powerful, but they"<br />
* p. 33: <br />
** "commonly mentioned on Haskell mailing lists pitfall of type functions" -> "one pitfall of type functions commonly mentioned..."<br />
** "the compiler should chose" -> "should the compiler choose"<br />
<br />
[[User:bjpop|BerniePope]] 06:18, Fri 15 May 2009 (UTC) Typo in Appendix B.<br />
<br />
"GHC should noat" -> "GHC should not"<br />
<br />
[[User:Tanimoto|tanimoto]] 02:17, 15 May 2009 (UTC) Typo in references<br />
<br />
In reference [32], page 30, Oleg's last name is misspelled as "Kiselov".<br />
<br />
<br />
[[User:Ryani|Ryani]] 23:01, 14 May 2009 (UTC) Fun paper! Comments:<br />
<br />
I was writing a generic finite map a while ago and determined that the generic memoized trie was better in almost all cases; it was simpler semantically and didn't have a significant performance difference. Then you have "type Map k v = Table k (Maybe v)". Is it worth calling out this special case in its own section?<br />
<br />
Also, in respose to ChrisKuklewicz, I think the type for "cons" is correct, but perhaps one instance should be given as an example.<br />
<br />
'''To Ryan Ingram''': Just to double-check: you are saying that the<br />
implementation of generic finite maps as <br />
"type Map k v = Table k (Maybe v)" is faster that the one given in Sec<br />
3.3? That is quite interesting!<br />
<br />
<br />
<br />
[[User:Dave Menendez|Dave Menendez]] 16:52, 14 May 2009 (UTC) On page 11, you refer to a "specialised instance for Table Int that uses some custom <br />
(but innite!) tree representation for Int." Was this meant to be Integer? Surely any tree representation for Int would be large but finite. <br />
<br />
-------------------<br />
Peter Verswyvelen and I have been working on some type family fun to give us generalised partial application (even to the point of being able to cope with giving arguments, but not a function). I don't know if it really makes any interesting point that you didn't already in the paper, but it's certainly fun...<br />
<br />
<haskell><br />
{-# LANGUAGE TypeFamilies, EmptyDataDecls, TypeOperators, FlexibleInstances, FlexibleContexts #-}<br />
<br />
module Burn2 where<br />
<br />
newtype V a = V a -- A value<br />
data B a = B -- A value we don't want to provide yet<br />
<br />
-- Type level homogenous lists (well just tuples in a list-like syntax really)<br />
data Nil a = Nil<br />
data a :& b = !a :& !b<br />
<br />
infixr 5 :& <br />
<br />
class Apply funargs where<br />
type Result funargs :: *<br />
apply :: funargs -> Result funargs<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (V (a->b) :& V c :& rest) where<br />
type Result (V (a->b) :& V c :& rest) = Result (V b :& rest)<br />
apply (V f :& V a :& rest) = apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (B (a->b) :& V c :& rest) where<br />
type Result (B (a->b) :& V c :& rest) = (a->b) -> Result (V b :& rest)<br />
apply (B :& V a :& rest) = \f -> apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (V (a->b) :& B c :& rest) where<br />
type Result (V (a->b) :& B c :& rest) = a -> Result (V b :& rest)<br />
apply (V f :& B :& rest) = \a -> apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (B (a->b) :& B c :& rest) where<br />
type Result (B (a->b) :& B c :& rest) = (a->b) -> a -> Result (V b :& rest)<br />
apply (B :& B :& rest) = \f a -> apply $ V (f a) :& rest<br />
<br />
instance Apply (V a :& Nil b) where<br />
type Result (V a :& Nil b) = a<br />
apply (V a :& Nil) = a<br />
<br />
instance Apply (B a :& Nil b) where<br />
type Result (B a :& Nil b) = B a<br />
apply (B :& Nil) = B<br />
<br />
v1 = apply (V 1 :& Nil)<br />
f1 = apply (B :& Nil)<br />
v2 = apply (V negate :& V 1 :& Nil)<br />
f3 = apply (V negate :& B :& Nil)<br />
v3 = apply (V f3 :& V 1 :& Nil)<br />
</haskell><br />
<br />
[[User:Beelsebob|Beelsebob]] 13:04, 14 May 2009 (UTC)<br />
<br />
'''To Beelsebob''': I'm afraid the code does not account for the most<br />
interesting case: a function that takes a dynamic value and returns<br />
a static result. So you need to deal with functions of the type<br />
V a -> B b or B a -> V b. The literature on partial evaluation<br />
describes this issue in detail. Our tagless-final paper (Sec 4.2 of<br />
the the journal version, Delaying binding-time analysis) has a short<br />
explanation, too.<br />
<br />
--------------------------------------<br />
<br />
End of section 2.2, I think "cons :: a -> [b] -> [ResTy a b]" should be "cons :: a -> [b] -> ResTy a b"<br />
<br />
[[User:ChrisKuklewicz|ChrisKuklewicz]] 15:28, 14 May 2009 (UTC)<br />
<br />
<br />
--------------------------------------<br />
<br />
End of page 19 with footnote 9. I could not simply copy and paste the URL because of a stray space after the '-' in http://okmij.org/ftp/Haskell/keyword- arguments.lhs<br />
<br />
[[User:ChrisKuklewicz|ChrisKuklewicz]] 16:08, 14 May 2009 (UTC)<br />
<br />
<br />
'''To Chris Kuklewicz''', regarding the problem with footnote 9. That is an<br />
odd problem that I could not reproduce. It seems xpdf lets me cut<br />
and paste the URL in question without introducing stray spaces. BTW,<br />
the type was correct, as Ryan Ingram described. We have implemented<br />
his suggestion so to remove the confusion.<br />
<br />
--------------------------------------<br />
<br />
Typo "Mounier" --> "Monnier"<br />
<br />
[[User:Tschrijvers|Tom Schrijvers]] 11:11, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
Contrary to what the introductions say, polymorphism over type constructors was not part of Haskell from the beginning. They were only introduced after Mark Jones showed how to do it in Gofer.<br />
<br />
[[User:Augustss|Augustss]] 14:30, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
Why do you say "Obviously, we want to declare algebraic data kinds, ..."?<br />
What's obvious about that? Many of us think that's the wrong way, and you should instead provide a way to lift ordinary data type to the kind level.<br />
<br />
[[User:Augustss|Augustss]] 15:36, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
I was really fascinated by section 5.2 where you track state in the types using a parameterized monad. However, the example code you use is rather underwhelming since it can be implemented by much simpler means. If there's only a fixed number of locks then they can be tracked using a fixed tuple and the whole type functions business is a bit superfluous (albeit still nice). To really reap the benefits of the machinery you set up you ought to have a function for creating new locks dynamically. Here's an example of how it can be done:<br />
<haskell><br />
type family Length p<br />
type instance Length Nil = Zero<br />
type instance Length (Cons l p) = Succ (Length p)<br />
<br />
type family NewLock p<br />
type instance NewLock Nil = Cons Unlocked Nil<br />
type instance NewLock (Cons l p) = Cons l (NewLock p)<br />
<br />
newLock :: Nat (Length p) =><br />
LockM p (NewLock p) (Lock (Length p))<br />
newLock = LockM (return mkLock)<br />
</haskell><br />
<br />
In order for this to work nicely we need a new run function as well. I've used an ordinary type class to check that all locks are unlocked, since this really is a predicate on the state and not a function. <br />
<br />
<haskell><br />
class AllUnlocked a<br />
<br />
instance AllUnlocked Nil<br />
instance AllUnlocked p => AllUnlocked (Cons Unlocked p)<br />
<br />
runNew :: AllUnlocked locks => LockM Nil locks a -> IO a<br />
runNew = unLockM<br />
</haskell><br />
<br />
I think the section becomes more convincing if you add dynamic creation of locks. Not to mention the increased sex appeal :-)<br />
<br />
[[User:Josef|Josef]] 16:58, 25 May 2009 (UTC)<br />
<br />
'''To Josef Svenningsson''': indeed the variable number of locks would have<br />
been sexier but it creates the problem of locks `leaking' out of scope<br />
(e.g., returned as the result of runNew and then used within another<br />
runNew computation, with disastrous results). In short, we need<br />
regions. Chung-chieh Shan and I have indeed implemented such a system,<br />
with a parameterized monad to track the state of the variable number of<br />
resources (file handles in our case). Please see Sec 6 of our<br />
Lightweight Monadic Regions paper. We used functional dependencies for<br />
type functions. Replacing functional dependencies with type functions<br />
is straightforward. Yet the staggering complexity of the code in Sec 6<br />
will remain. I'm afraid this makes the example too complex for this<br />
paper; rather than attracting users to type functions we would scare<br />
all of them away.<br />
--------------------------------------<br />
<br />
It would be very nice if you published a bundle or repository somewhere containing the Haskell source from the paper. At the very least it would be nice with a comment on which version of GHC one should have and what flags are required. The reason I'm asking is that I had a bit of trouble with this. For instance, just saying {-# LANGUAGE TypeFamilies #-} didn't enable type equality constraints in the parser. I had to add ScopedTypeVariables which felt rather arbitrary.<br />
<br />
[[User:Josef|Josef]] 16:58, 25 May 2009 (UTC)</div>Mvanierhttps://wiki.haskell.org/index.php?title=AmeroHaskell&diff=16906AmeroHaskell2007-11-19T08:09:43Z<p>Mvanier: </p>
<hr />
<div>AmeroHaskell, a Haskell get together for/in the SouthEastern USA.<br />
Now a Haskell get together(s) anywhere in the USA with at least one in Portland, OR.<br />
<br />
== Likely Attendees ==<br />
<br />
=== Western ===<br />
<br />
* [[User:Taral|Taral]] - Seattle, WA, will travel.<br />
* [[DonStewart]], in OR, but would travel for haskell<br />
* [[TimChevalier]] - Portland, OR. Might be willing to travel, depending on where and when.<br />
* [[User:CliffordBeshers|CliffordBeshers]] - San Diego, CA, but would consider travelling.<br />
* [[JohnMeacham]] - Pasadena, CA. might be able to travel depending on when. (would prefer somewhere on west coast)<br />
* [[GregFitzgerald]] - San Diego, CA<br />
* [[BryanOSullivan]] - San Francisco, CA, will travel.<br />
* [[Derek Elkins]], in TX, would travel some, probably would only stay for a day or two.<br />
* [http://www.travishartwell.net/blog/ Travis B. Hartwell] aka Nafai Willing to travel some, probably can't take any time off of work but most weekends are good except Nov. 2-4 and 16-18.<br />
* [[JustinBailey]] - Can't really travel, but in Portland, OR.<br />
* [[JohnDorsey]] - In Houston, TX. Slight chance of travel elsewhere.<br />
* [[MikeVanier]] - Pasadena, CA. Could travel depending on the date, prefer west coast.<br />
<br />
=== Eastern ===<br />
<br />
* [[Rahul Kapoor]] - Providence, RI, will travel for Haskell.<br />
* [[Adam Peacock]] - NYC, I might come, but Nov 24 to Dec 9 I'm traveling elsewhere.<br />
* [http://byorgey.wordpress.com Brent Yorgey] (byorgey) - Washington, DC. <br />
* [[Bjorn Buckwalter]] - Washington, DC. Unlikely to travel.<br />
* [[Betty]] - Raleigh, NC<br />
* [[Dino]] Morelli - Raleigh, North Carolina. Will travel some, can stay somewhere overnight(s). Week of Oct 13-20 is not doable.<br />
* [[Peter Gavin]] - Tallahassee, FL, willing to drive a few hours; weekends are best<br />
* [[Bernard Putersznit]] - Ocala, FL, willing to drive a few hours; any day of the week. Available from November onward.<br />
* [[ShaeErisson]] - located in Tuscaloosa, Alabama - pretty much any date is good for me.<br />
<br />
== Possible locations ==<br />
<br />
* Portland, OR<br />
* Although this is in the North East, Credit Suisse - contact Adam Peacock<br />
<br />
== Potential Presenters ==<br />
<br />
* [[Derek Elkins]] - I can provide a talk for categorical ideas that are directly applicable in Haskell (e.g. free monads, initial algebras, etc.) and/or something on using types to enforce invariants without going ''too'' crazy (e.g. wrapper types, phantom types, type class traits, reasonable examples of type level programming)<br />
* [[TimChevalier]] - if you're really hard up for speakers, I could scrape something up.<br />
<br />
== When ==<br />
<br />
* For a Portland meeting, probably in a January/February time-frame<br />
* Maybe during SIGCSE in Portland March 12-15<br />
<br />
[[Category:Events]]</div>Mvanierhttps://wiki.haskell.org/index.php?title=Talk:SantaClausProblem&diff=9706Talk:SantaClausProblem2006-12-23T19:21:32Z<p>Mvanier: </p>
<hr />
<div>= Beautiful concurrency =<br />
<br />
I am writing a chapter for a book called "Beautiful code", edited by Greg Wilson. My [http://research.microsoft.com/~simonpj/tmp/beautiful.ps draft chapter] is about Software Transactional Memory in Haskell.<br />
<br />
I would welcome any comments or questions you have on the paper, or constructive suggestions for improving it; the more concrete the better. <br />
<br />
The book is aimed at a general audience of programmers, <em>not</em> Haskell geeks, so I have tried to explain everything necessary as I go along. So if you are not a Haskell expert, your input would be particularly valuable to me.<br />
<br />
You can email me directly (simonpj@microsoft.com), or add Wiki talk notes below.<br />
<br />
----------<br />
<br />
[[User:Simonpj|Simonpj]] 14:26, 22 December 2006 (UTC) To add a note, begin with four tilde signs <nowiki>~~~~</nowiki>; the Wiki will fill in your user name and date.<br />
<br />
----------<br />
<br />
[[User:ArthurVanLeeuwen|ArthurVanLeeuwen]] 16:25, 22 December 2006 (UTC) There's a couple of typos in the paper as it is now. More importantly, the footnote on page 2 has (hGetLine h "hello") where it should state (hPutStr h "hello").<br />
<br />
[[User:NeilMitchell|Neil Mitchell]] 16:28, 22 December 2006 (UTC) Sect 1, Para 2. If we want to write parallel program[s] - missing s.<br />
<br />
<br />
[[User:Steven807|Steven807]] 17:14, 22 December 2006 (UTC) There is no definition or description of '''check'''<br />
<br />
[[User:Tibbe|Tibbe]] 18:33, 22 December 2006 (UTC); The footnote on page 2 now has a incorrectly capitalized T in hPutSTr.<br />
<br />
[[User:Fanf|Fanf]] 18:51, 22 December 2006 (UTC) page 1 para 2 "as well shall see" should be "as we shall see"<br />
<br />
[[User:Fanf|Fanf]] 18:51, 22 December 2006 (UTC) page 3 "a bit like *t in C" should be "a bit like t* in C" since t is a type<br />
<br />
[[User:Garious|Garious]] 18:56, 22 December 2006 (UTC) page 10 "at which point An elf" should be "at which point an elf"<br />
<br />
[[User:Garious|Garious]] 18:58, 22 December 2006 (UTC) page 10 "Here, then is a possible" should be "Here then, is a possible"<br />
<br />
[[User:Garious|Garious]] 19:16, 22 December 2006 (UTC) page 11 "Again, we define Group is declared" whaaa? maybe: "Group is declared as a data type with constructor MkGroup. MkGroup is passed the Group's capacity, and a TVar containing the number of current members and the Group's two Gates."<br />
<br />
[[User:Garious|Garious]] 19:16, 22 December 2006 (UTC) page 11 "Creating a new Group is simply..." Is a process of three somewhat-abstract steps simple enough to say 'simply'? Instead, maybe show the code and let the reader think, "Hey, that's simple!"<br />
<br />
[[User:Rycee|Rycee]] 20:46, 22 December 2006 (UTC) Page 4. You probably want to change "... the action a does ..." to "... the action act does ..."<br />
<br />
[[User:Rycee|Rycee]] 20:46, 22 December 2006 (UTC) Page 8. Typographic nitpick: The space after "i.e." looks wide, perhaps you forgot to write "i.e.\ " to force a regular (non sentence ending) space in LaTeX?<br />
<br />
[[User:MichalPalka|MichalPalka]] 22:32, 22 December 2006 (UTC) You could add a reference to SQL and triggers. They are similar in that it is programming with transations and seeing familiar names will make applied programmers feel more comfortable.<br />
<br />
[[User:DavidHouse|DavidHouse]] 22:55, 22 December 2006 (UTC) Page 3, "That is, return v is a function that, when performed, does no side effects and returns v." Your use of 'that is' implies that you could deduce the fact that it does no side effects from the type signature just given, which isn't true. It's an auxiliary property of 'return'. Maybe just miss out the 'that is'.<br />
<br />
[[User:DavidHouse|DavidHouse]] 23:04, 22 December 2006 (UTC) Bottom of Page 4, "Then 'atomically act' grabs the lock, performs the action 'at',". Missing 'c' out of 'at'.<br />
<br />
[[User:DavidHouse|DavidHouse]] 23:23, 22 December 2006 (UTC) Page 5, "Then 'withdraw' is an STM action that adds amount to the balance in the account." 1) For consistency with the rest of the paper, it should be "Then 'withdraw account ammount'..." 2) withdraw subtracts, not adds, to the amount in the account.<br />
<br />
[[User:DavidHouse|DavidHouse]] 23:40, 22 December 2006 (UTC) Page 9, you probably want to mention that ++ is string concatenation.<br />
<br />
[[User:DavidHouse|DavidHouse]] 23:45, 22 December 2006 (UTC) Page 10, I would expect to see the type signatures for the Gate interface rewritten alongside their definitions.<br />
<br />
[[User:DavidHouse|DavidHouse]] 23:47, 22 December 2006 (UTC) Page 9/10, algebraic datatypes are a little weird for the non-initiated, especially with constructors that don't appear to do anything ("Where do you define MkGate?" etc.). You might want to liken them to C's structs, and explain the constructors as tags?<br />
<br />
[[User:DavidHouse|DavidHouse]] 23:57, 22 December 2006 (UTC) Page 13, I don't think you sufficiently explain 'sequence'. You may wish to add a sentence along the lines of "'sequence' is a function that takes a list of IO actions and returns the action that, when executed, runs each of the actions you passed it in turn."<br />
<br />
[[User:Dalejordan|Dalejordan]] 02:15, 23 December 2006 (UTC) For the sake of us newbs you might mention in Section 2.1 how all these actions ever get performed. Also, in your description of nTimes I think it would be clearer to say it creates a composite action that performs its argument action n times, rather than say it performs it (directly) n times, even though the value of n is not yet known. Another example of the "beauty" of first class actions (and recursion).<br />
<br />
[[User:Brecknell|Brecknell]] 03:29, 23 December 2006 (UTC) Page 7: withdraw should subtract, not add amount to the balance (sadly). Also, since this withdraw has different semantics to the version on p5, you may want to consider giving it a different name.<br />
<br />
[[User:Brecknell|Brecknell]] 03:29, 23 December 2006 (UTC) Page 8, towards the end of section 2.4: Two instances of "withdraw" should be "withdraw2", one in the function definition and one in the comment.<br />
<br />
[[User:Brecknell|Brecknell]] 05:04, 23 December 2006 (UTC) In the problem definition, "Santa repeatedly sleeps until wakened...", but with the definition of "forever" given in the text, and without some sort of asynchronous signalling, it looks to me like Santa will sleep for at least as long as his random number generator tells him to. Perhaps move the sleep out of forever and into elf and reindeer, then Santa will just sleep in awaitGroup.<br />
<br />
[[User:Mvanier|Mvanier]] 19:21, 23 December 2006 (UTC) In section 3.3, "sequence" might as well just be "sequence_". It's confusing to return a list of unit values and not do anything with them. In section 5, I think that the problem with composing lock-based concurrent functions could be explained better; the statement "instead we must expose the locking protocol" could be expanded to show why this is the case.</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4645IO inside2006-07-04T08:59:05Z<p>Mvanier: fixed a typo</p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on mutable global variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems, though: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# Because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value twice.<br />
# Even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return an additional fake result from 'getchar' that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating because we throw it away! Therefore it won't feel obliged to execute the calls in the order we want. How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the excessively-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. You can think of the type "IO Char" as meaning "take the current RealWorld, do something to it, and return a Char and a (possibly changed) RealWorld". Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld<br />
that gets used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (''i.e.'', here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally, you may want to know how much passing these RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO (and also other monads, but that's beyond the scope of this tutorial). 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement; for instance,<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of one of the so-called "binding operators", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result<br />
the result of its second action only. On the other hand, the '>>=' binding operator (note the extra '=' at the end) allows us to use the result of its first action - it gets passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a -> IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action" (more precisely, a function which returns an IO action), namely "a -> IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a -> IO b". It's the way<br />
the '<-' binding is processed - the name on the left-hand side of '<-' just becomes a parameter of subsequent operations represented as one large IO action. Note also that if 'action1' has type "IO a" then 'x' will just have type "a"; you can think of the effect of '<-' as "unpacking" the IO value of 'action1' into 'x'. Note also that '<-' is not a true operator; it's pure syntax, just like 'do' itself. Its meaning results only from the way it gets desugared.<br />
<br />
Look at the next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted the parentheses here; both the '>>' and the '>>=' operators are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative language background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed even for non-negative values of 'a'. If you need to escape from the middle of an IO procedure, you can use the 'if' statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a -> b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If that's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, every name in Haskell is bound to one fixed (immutable) value. This greatly simplifies understanding algorithms and code optimization, but it's inappropriate in some cases. As we all know, there are plenty of algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0, a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To complete the picture, these three calls may be rearranged in any order because they appear to be independent of each<br />
other. This is obviously not what was intended. What's the solution? You already know this - use IO actions! Using IO actions guarantees that:<br />
<br />
# the execution order will be retained as written<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0, a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action depends not<br />
only on the variable involved but also on the moment this operation is performed so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a, b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) into 'a' this element's value is changed to 64 and then read again into 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick (as it usually is in Haskell :)).<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters, returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value. That can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of the 'let' bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - the execution order will be defined by the data dependency with respect to the <br />
"world" values that get passed around. Let's see what this 'main' looks like in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, we've eliminated two of the 'let' bindings and left only the one defining 'get2chars'. The non-'let' statements are executed in the exact order in which they're written, because they pass the "world" value from statement to statement as we described above. Thus, this version of the function is much easier to understand because we don't have to mentally figure out the data dependency of the "world" value.<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main' (either directly in the 'main' function, or indirectly in an IO function called from 'main'). Until that's done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (as we did above), save them in data<br />
structures, pass them as function parameters and return them as results - and<br />
they won't be performed until you give them the magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they aren't really required. If you still can't believe that these actions won't be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in a 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that "IO a" is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as a parameter?<br />
Just look at the definition of 'when'. Hey, we can buy, sell, and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed one after another (in the same order that they occurred in the list) to "compute the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' function as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
Most programming languages don't allow you to define control structures at all, and those that do often require you to use a macro-expansion system. In Haskell, control structures are just trivial functions anyone can write.<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the result of a function? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "These 'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body in 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
That's a little better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? An even shorter version is this:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
This way of using IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. One thing this can be used for is to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my programs has a module which is a memory suballocator. It receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside the memoryAllocator procedure. Because the creation of these references is a part of the memoryAllocator IO actions chain, a new independent set of references will be created for each memory block for which<br />
memoryAllocator is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references are read and written in the 'alloc' and 'free' definitions (we'll implement a very simple memory allocator for this example):<br />
<br />
<haskell><br />
...<br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with a mutable variable that holds each figure's current screen location. The<br />
type of this variable will be "IORef Point". This variable should be created in the figure constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can test the code which moves figures around:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that's intended to simulate a C++/Java-style interface. The record can also include values, IORefs, pure functions - in short, any type of data. For example, we can easily add to the Figure interface fields for area and origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you're trying to write a procedure that reads the contents of a file with a given name, and you try to write it as a pure (non-IO) function:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining readContents as a pure function will certainly simplify the code that uses it. But it will also create problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if the file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all non-IO functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in order to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that produces this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special (and dangerous) procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating; it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is determined by a value's necessity - the language computes only the values that are really required to calculate the final result. But what does this mean with respect to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain. What guarantee do we have that they will be run at all? None. The only time they will be run is if running them is required to compute the overall function result (which in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used (because the implicit "world" value it returns ''will'' be used). You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via the implicit "world" values that are passed from each IO action to the next.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you're sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
a small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' syntactic sugar we've seen above. For example, here's a particularly convoluted way to compute the integer that comes after zero:<br />
<br />
<haskell><br />
one :: Int<br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates its first argument before<br />
returning the value of the second one).<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: I should say that I'm not describing<br />
here exactly what a monad is (I don't even completely understand it myself) and my explanation shows only one _possible_ way to implement the IO monad in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is some good news: first, the monad understanding you've just acquired will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of the world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result of type "a", or if an error occurs then "IOError". The lack of the World on the right-hand side of the function can only be done because the compiler knows special things about the IO type, and won't overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI and STM at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
<br />
== To-do list ==<br />
<br />
If you are interested in adding more information to this manual, please add your questions/topics here.<br />
<br />
Topics:<br />
* fixIO and 'mdo'<br />
* ST monad<br />
* Q monad<br />
<br />
Questions:<br />
* split '>>='/'>>'/return section and 'do' section, more examples of using binding operators<br />
* IORef detailed explanation (==const*), usage examples, syntax sugar, unboxed refs<br />
* control structures developing - much more examples<br />
* unsafePerformIO usage examples: global variable, ByteString, other examples<br />
* actual GHC implementation - how to write low-level routines on example of newIORef implementation<br />
<br />
This manual is collective work, so feel free to add more information to it yourself. The final goal is to collectively develop a comprehensive manual for using the IO monad.<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4643IO inside2006-07-04T08:51:49Z<p>Mvanier: More proofreading and clarifications -- it should be pretty much done now.</p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on mutable global variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems, though: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# Because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value twice.<br />
# Even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return an additional fake result from 'getchar' that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating because we throw it away! Therefore it won't feel obliged to execute the calls in the order we want. How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the excessively-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. You can think of the type "IO Char" as meaning "take the current RealWorld, do something to it, and return a Char and a (possibly changed) RealWorld". Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld<br />
that gets used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (''i.e.'', here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally, you may want to know how much passing these RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO (and also other monads, but that's beyond the scope of this tutorial). 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement; for instance,<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of one of the so-called "binding operators", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result<br />
the result of its second action only. On the other hand, the '>>=' binding operator (note the extra '=' at the end) allows us to use the result of its first action - it gets passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a -> IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action" (more precisely, a function which returns an IO action), namely "a -> IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a -> IO b". It's the way<br />
the '<-' binding is processed - the name on the left-hand side of '<-' just becomes a parameter of subsequent operations represented as one large IO action. Note also that if 'action1' has type "IO a" then 'x' will just have type "a"; you can think of the effect of '<-' as "unpacking" the IO value of 'action1' into 'x'. Note also that '<-' is not a true operator; it's pure syntax, just like 'do' itself. Its meaning results only from the way it gets desugared.<br />
<br />
Look at the next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted the parentheses here; both the '>>' and the '>>=' operators are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative language background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed even for non-negative values of 'a'. If you need to escape from the middle of an IO procedure, you can use the 'if' statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a -> b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If that's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, every name in Haskell is bound to one fixed (immutable) value. This greatly simplifies understanding algorithms and code optimization, but it's inappropriate in some cases. As we all know, there are plenty of algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0, a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To complete the picture, these three calls may be rearranged in any order because they appear to be independent of each<br />
other. This is obviously not what was intended. What's the solution? You already know this - use IO actions! Using IO actions guarantees that:<br />
<br />
# the execution order will be retained as written<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0, a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action depends not<br />
only on the variable involved but also on the moment this operation is performed so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a, b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) into 'a' this element's value is changed to 64 and then read again into 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick (as it usually is in Haskell :)).<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters, returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value. That can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of the 'let' bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - the execution order will be defined by the data dependency with respect to the <br />
"world" values that get passed around. Let's see what this 'main' looks like in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, we've eliminated two of the 'let' bindings and left only the one defining 'get2chars'. The non-'let' statements are executed in the exact order in which they're written, because they pass the "world" value from statement to statement as we described above. Thus, this version of the function is much easier to understand because we don't have to mentally figure out the data dependency of the "world" value.<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main' (either directly in the 'main' function, or indirectly in an IO function called from 'main'). Until that's done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (as we did above), save them in data<br />
structures, pass them as function parameters and return them as results - and<br />
they won't be performed until you give them the magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they aren't really required. If you still can't believe that these actions won't be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in a 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that "IO a" is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as a parameter?<br />
Just look at the definition of 'when'. Hey, we can buy, sell, and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed one after another (in the same order that they occurred in the list) to "compute the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' function as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
Most programming languages don't allow you to define control structures at all, and those that do often require you to use a macro-expansion system. In Haskell, control structures are just trivial functions anyone can write.<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the result of a function? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "These 'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body in 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
That's a little better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? An even shorter version is this:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
This way of using IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. One thing this can be used for is to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my programs has a module which is a memory suballocator. It receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside the memoryAllocator procedure. Because the creation of these references is a part of the memoryAllocator IO actions chain, a new independent set of references will be created for each memory block for which<br />
memoryAllocator is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references are read and written in the 'alloc' and 'free' definitions (we'll implement a very simple memory allocator for this example):<br />
<br />
<haskell><br />
...<br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with a mutable variable that holds each figure's current screen location. The<br />
type of this variable will be "IORef Point". This variable should be created in the figure constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can test the code which moves figures around:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that's intended to simulate a C++/Java-style interface. The record can also include values, IORefs, pure functions - in short, any type of data. For example, we can easily add to the Figure interface fields for area and origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you're trying to write a procedure that reads the contents of a file with a given name, and you try to write it as a pure (non-IO) function:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining readContents as a pure function will certainly simplify the code that uses it. But it will also create problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if the file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all non-IO functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in order to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that produces this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special (and dangerous) procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating; it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is determined by a value's necessity - the language computes only the values that are really required to calculate the final result. But what does this mean with respect to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain. What guarantee do we have that they will be run at all? None. The only time they will be run is if running them is required to compute the overall function result (which in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used (because the implicit "world" value it returns ''will'' be used). You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via the implicit "world" values that are passed from each IO action to the next.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you're sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
a small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' syntactic sugar we've seen above. For example, here's a particularly convoluted way to compute the integer that comes after zero:<br />
<br />
<haskell><br />
one :: Int<br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates it's first argument before<br />
returning the value of the second one).<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: I should say that I'm not describing<br />
here exactly what a monad is (I don't even completely understand it myself) and my explanation shows only one _possible_ way to implement the IO monad in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is some good news: first, the monad understanding you've just acquired will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of the world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result of type "a", or if an error occurs then "IOError". The lack of the World on the right-hand side of the function can only be done because the compiler knows special things about the IO type, and won't overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI and STM at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
<br />
== To-do list ==<br />
<br />
If you are interested in adding more information to this manual, please add your questions/topics here.<br />
<br />
Topics:<br />
* fixIO and 'mdo'<br />
* ST monad<br />
* Q monad<br />
<br />
Questions:<br />
* split '>>='/'>>'/return section and 'do' section, more examples of using binding operators<br />
* IORef detailed explanation (==const*), usage examples, syntax sugar, unboxed refs<br />
* control structures developing - much more examples<br />
* unsafePerformIO usage examples: global variable, ByteString, other examples<br />
* actual GHC implementation - how to write low-level routines on example of newIORef implementation<br />
<br />
This manual is collective work, so feel free to add more information to it yourself. The final goal is to collectively develop a comprehensive manual for using the IO monad.<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4641IO inside2006-07-04T08:28:33Z<p>Mvanier: More proofreading and clarifications.</p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on mutable global variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems, though: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# Because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value twice.<br />
# Even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return an additional fake result from 'getchar' that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating because we throw it away! Therefore it won't feel obliged to execute the calls in the order we want. How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the excessively-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. You can think of the type "IO Char" as meaning "take the current RealWorld, do something to it, and return a Char and a (possibly changed) RealWorld". Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld<br />
that gets used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (''i.e.'', here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally, you may want to know how much passing these RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO (and also other monads, but that's beyond the scope of this tutorial). 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement; for instance,<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of one of the so-called "binding operators", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result<br />
the result of its second action only. On the other hand, the '>>=' binding operator (note the extra '=' at the end) allows us to use the result of its first action - it gets passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a -> IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action" (more precisely, a function which returns an IO action), namely "a -> IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a -> IO b". It's the way<br />
the '<-' binding is processed - the name on the left-hand side of '<-' just becomes a parameter of subsequent operations represented as one large IO action. Note also that if 'action1' has type "IO a" then 'x' will just have type "a"; you can think of the effect of '<-' as "unpacking" the IO value of 'action1' into 'x'. Note also that '<-' is not a true operator; it's pure syntax, just like 'do' itself. Its meaning results only from the way it gets desugared.<br />
<br />
Look at the next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted the parentheses here; both the '>>' and the '>>=' operators are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative language background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed even for non-negative values of 'a'. If you need to escape from the middle of an IO procedure, you can use the 'if' statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a -> b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If that's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, every name in Haskell is bound to one fixed (immutable) value. This greatly simplifies understanding algorithms and code optimization, but it's inappropriate in some cases. As we all know, there are plenty of algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0, a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To complete the picture, these three calls may be rearranged in any order because they appear to be independent of each<br />
other. This is obviously not what was intended. What's the solution? You already know this - use IO actions! Using IO actions guarantees that:<br />
<br />
# the execution order will be retained as written<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0, a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action depends not<br />
only on the variable involved but also on the moment this operation is performed so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a, b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) into 'a' this element's value is changed to 64 and then read again into 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick (as it usually is in Haskell :)).<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters, returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value. That can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of the 'let' bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - the execution order will be defined by the data dependency with respect to the <br />
"world" values that get passed around. Let's see what this 'main' looks like in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, we've eliminated two of the 'let' bindings and left only the one defining 'get2chars'. The non-'let' statements are executed in the exact order in which they're written, because they pass the "world" value from statement to statement as we described above. Thus, this version of the function is much easier to understand because we don't have to mentally figure out the data dependency of the "world" value.<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main' (either directly in the 'main' function, or indirectly in an IO function called from 'main'). Until that's done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (as we did above), save them in data<br />
structures, pass them as function parameters and return them as results - and<br />
they won't be performed until you give them the magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they aren't really required. If you still can't believe that these actions won't be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in a 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that "IO a" is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as a parameter?<br />
Just look at the definition of 'when'. Hey, we can buy, sell, and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed one after another (in the same order that they occurred in the list) to "compute the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' function as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
Most programming languages don't allow you to define control structures at all, and those that do often require you to use a macro-expansion system. In Haskell, control structures are just trivial functions anyone can write.<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the result of a function? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "These 'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body in 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
That's a little better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? An even shorter version is this:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
This way of using IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. One thing this can be used for is to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my programs has a module which is a memory suballocator. It receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside the memoryAllocator procedure. Because the creation of these references is a part of the memoryAllocator IO actions chain, a new independent set of references will be created for each memory block for which<br />
memoryAllocator is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references are read and written in the 'alloc' and 'free' definitions (we'll implement a very simple memory allocator for this example):<br />
<br />
<haskell><br />
...<br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables that holds the figure's current screen location. Their<br />
types will be "IORef Point". These variables should be created in the figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that simulates a C++/Java-style interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you try to write a procedure that reads the contents of a file<br />
with a given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as a pure function will simplify the code that uses it, I<br />
agree. But this creates problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that procures this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating, it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is ruled by a value's necessity - the language computes only the values that a really required to calculate the final result. But what does this mean according to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What guarantees that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute the overall function<br />
result (that in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used. You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via "world" values.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' sugar we've seen above:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI and STM at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
<br />
== To-do list ==<br />
<br />
If you are interested in adding more information to this manual, please add your questions/topics here:<br />
<br />
* fixIO and 'mdo'<br />
* ST monad<br />
* Q monad<br />
<br />
My own to-do list (Bulat):<br />
* split '>>='/'>>'/return section and 'do' section, more examples of using binding operators<br />
* IORef detailed explanation (==const*), usage examples, syntax sugar, unboxed refs<br />
* control structures developing - much more examples<br />
* unsafePerformIO usage examples: global variable, ByteString, other examples<br />
* actual GHC implementation - how to write low-level routines on example of newIORef implementation<br />
<br />
This manual is collective work, so feel free to add more information to it yourself. The final goal is to collectively develop comprehesive manual of using IO monad.<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4640IO inside2006-07-04T08:15:44Z<p>Mvanier: More proofreading and clarifications.</p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on mutable global variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems, though: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# Because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value twice.<br />
# Even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return an additional fake result from 'getchar' that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating because we throw it away! Therefore it won't feel obliged to execute the calls in the order we want. How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the excessively-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. You can think of the type "IO Char" as meaning "take the current RealWorld, do something to it, and return a Char and a (possibly changed) RealWorld". Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld<br />
that gets used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (''i.e.'', here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally, you may want to know how much passing these RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO (and also other monads, but that's beyond the scope of this tutorial). 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement; for instance,<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of one of the so-called "binding operators", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result<br />
the result of its second action only. On the other hand, the '>>=' binding operator (note the extra '=' at the end) allows us to use the result of its first action - it gets passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a -> IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action" (more precisely, a function which returns an IO action), namely "a -> IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a -> IO b". It's the way<br />
the '<-' binding is processed - the name on the left-hand side of '<-' just becomes a parameter of subsequent operations represented as one large IO action. Note also that if 'action1' has type "IO a" then 'x' will just have type "a"; you can think of the effect of '<-' as "unpacking" the IO value of 'action1' into 'x'. Note also that '<-' is not a true operator; it's pure syntax, just like 'do' itself. Its meaning results only from the way it gets desugared.<br />
<br />
Look at the next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted the parentheses here; both the '>>' and the '>>=' operators are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative language background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed even for non-negative values of 'a'. If you need to escape from the middle of an IO procedure, you can use the 'if' statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a -> b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If that's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, every name in Haskell is bound to one fixed (immutable) value. This greatly simplifies understanding algorithms and code optimization, but it's inappropriate in some cases. As we all know, there are plenty of algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0, a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To complete the picture, these three calls may be rearranged in any order because they appear to be independent of each<br />
other. This is obviously not what was intended. What's the solution? You already know this - use IO actions! Using IO actions guarantees that:<br />
<br />
# the execution order will be retained as written<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0, a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action depends not<br />
only on the variable involved but also on the moment this operation is performed so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a, b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) into 'a' this element's value is changed to 64 and then read again into 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick (as it usually is in Haskell :)).<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters, returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value. That can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of the 'let' bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - the execution order will be defined by the data dependency with respect to the <br />
"world" values that get passed around. Let's see what this 'main' looks like in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, we've eliminated two of the 'let' bindings and left only the one defining 'get2chars'. The non-'let' statements are executed in the exact order in which they're written, because they pass the "world" value from statement to statement as we described above. Thus, this version of the function is much easier to understand because we don't have to mentally figure out the data dependency of the "world" value.<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main' (either directly in the 'main' function, or indirectly in an IO function called from 'main'). Until that's done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (as we did above), save them in data<br />
structures, pass them as function parameters and return them as results - and<br />
they won't be performed until you give them the magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they aren't really required. If you still can't believe that these actions won't be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in a 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that "IO a" is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as a parameter?<br />
Just look at the definition of 'when'. Hey, we can buy, sell, and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed one after another (in the same order that they occurred in the list) to "compute the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' function as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
Most programming languages don't allow you to define control structures at all, and those that do often require you to use a macro-expansion system. In Haskell, control structures are just trivial functions anyone can write.<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my program's modules is the memory suballocator. It<br />
receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside this procedure. Because the creation of these references is<br />
a part of the 'memoryAllocator' IO actions chain, a new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement a very simple memory allocator) are<br />
read and written in the 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables that holds the figure's current screen location. Their<br />
types will be "IORef Point". These variables should be created in the figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that simulates a C++/Java-style interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you try to write a procedure that reads the contents of a file<br />
with a given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as a pure function will simplify the code that uses it, I<br />
agree. But this creates problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that procures this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating, it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is ruled by a value's necessity - the language computes only the values that a really required to calculate the final result. But what does this mean according to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What guarantees that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute the overall function<br />
result (that in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used. You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via "world" values.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' sugar we've seen above:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI and STM at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
<br />
== To-do list ==<br />
<br />
If you are interested in adding more information to this manual, please add your questions/topics here:<br />
<br />
* fixIO and 'mdo'<br />
* ST monad<br />
* Q monad<br />
<br />
My own to-do list (Bulat):<br />
* split '>>='/'>>'/return section and 'do' section, more examples of using binding operators<br />
* IORef detailed explanation (==const*), usage examples, syntax sugar, unboxed refs<br />
* control structures developing - much more examples<br />
* unsafePerformIO usage examples: global variable, ByteString, other examples<br />
* actual GHC implementation - how to write low-level routines on example of newIORef implementation<br />
<br />
This manual is collective work, so feel free to add more information to it yourself. The final goal is to collectively develop comprehesive manual of using IO monad.<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4637IO inside2006-07-04T04:06:25Z<p>Mvanier: Proofreading and clarifications.</p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on mutable global variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems, though: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# Because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value twice.<br />
# Even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return an additional fake result from 'getchar' that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating because we throw it away! Therefore it won't feel obliged to execute the calls in the order we want. How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the excessively-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. You can think of the type "IO Char" as meaning "take the current RealWorld, do something to it, and return a Char and a (possibly changed) RealWorld". Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld<br />
that gets used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (''i.e.'', here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally, you may want to know how much passing these RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO (and also other monads, but that's beyond the scope of this tutorial). 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement; for instance,<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of one of the so-called "binding operators", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result<br />
the result of its second action only. On the other hand, the '>>=' binding operator (note the extra '=' at the end) allows us to use the result of its first action - it gets passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a -> IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action" (more precisely, a function which returns an IO action), namely "a -> IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a -> IO b". It's the way<br />
the '<-' binding is processed - the name on the left-hand side of '<-' just becomes a parameter of subsequent operations represented as one large IO action. Note also that if 'action1' has type "IO a" then 'x' will just have type "a"; you can think of the effect of '<-' as "unpacking" the IO value of 'action1' into 'x'. Note also that '<-' is not a true operator; it's pure syntax, just like 'do' itself. Its meaning results only from the way it gets desugared.<br />
<br />
Look at the next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both the '>>' and the '>>=' operators are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative language background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed even for non-negative values of 'a'. If you need to escape from the middle of an IO procedure, you can use the 'if' statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a -> b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If that's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my program's modules is the memory suballocator. It<br />
receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside this procedure. Because the creation of these references is<br />
a part of the 'memoryAllocator' IO actions chain, a new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement a very simple memory allocator) are<br />
read and written in the 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables that holds the figure's current screen location. Their<br />
types will be "IORef Point". These variables should be created in the figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that simulates a C++/Java-style interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you try to write a procedure that reads the contents of a file<br />
with a given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as a pure function will simplify the code that uses it, I<br />
agree. But this creates problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that procures this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating, it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is ruled by a value's necessity - the language computes only the values that a really required to calculate the final result. But what does this mean according to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What guarantees that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute the overall function<br />
result (that in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used. You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via "world" values.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' sugar we've seen above:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4636IO inside2006-07-04T03:45:23Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on mutable global variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems, though: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# Because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value twice.<br />
# Even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return an additional fake result from 'getchar' that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating because we throw it away! Therefore it won't feel obliged to execute the calls in the order we want. How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the excessively-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. You can think of the type "IO Char" as meaning "take the current RealWorld, do something to it, and return a Char and a (possibly changed) RealWorld". Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld<br />
that gets used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (''i.e.'', here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally, you may want to know how much passing these RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my program's modules is the memory suballocator. It<br />
receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside this procedure. Because the creation of these references is<br />
a part of the 'memoryAllocator' IO actions chain, a new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement a very simple memory allocator) are<br />
read and written in the 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables that holds the figure's current screen location. Their<br />
types will be "IORef Point". These variables should be created in the figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that simulates a C++/Java-style interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you try to write a procedure that reads the contents of a file<br />
with a given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as a pure function will simplify the code that uses it, I<br />
agree. But this creates problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that procures this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating, it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is ruled by a value's necessity - the language computes only the values that a really required to calculate the final result. But what does this mean according to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What guarantees that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute the overall function<br />
result (that in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used. You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via "world" values.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' sugar we've seen above:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4635IO inside2006-07-04T03:44:18Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on mutable global variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems, though: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# Because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value twice.<br />
# Even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return an additional fake result from 'getchar' that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating because we throw it away! Therefore it won't feel obliged to execute the calls in the order we want. How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the excessively-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. You can think of the type "IO Char" as meaning "take the current RealWorld, do something to it, return a Char and a (possibly changed) RealWorld". Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld<br />
that gets used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (''i.e.'', here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally, you may want to know how much passing these RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my program's modules is the memory suballocator. It<br />
receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside this procedure. Because the creation of these references is<br />
a part of the 'memoryAllocator' IO actions chain, a new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement a very simple memory allocator) are<br />
read and written in the 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables that holds the figure's current screen location. Their<br />
types will be "IORef Point". These variables should be created in the figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that simulates a C++/Java-style interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you try to write a procedure that reads the contents of a file<br />
with a given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as a pure function will simplify the code that uses it, I<br />
agree. But this creates problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that procures this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating, it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is ruled by a value's necessity - the language computes only the values that a really required to calculate the final result. But what does this mean according to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What guarantees that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute the overall function<br />
result (that in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used. You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via "world" values.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' sugar we've seen above:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4634IO inside2006-07-04T03:37:43Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on mutable global variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems, though: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# Because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value twice.<br />
# Even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return an additional fake result from 'getchar' that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating because we throw it away! Therefore it won't feel obliged to execute the calls in the order we want. How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the excessively-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my program's modules is the memory suballocator. It<br />
receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside this procedure. Because the creation of these references is<br />
a part of the 'memoryAllocator' IO actions chain, a new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement a very simple memory allocator) are<br />
read and written in the 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables that holds the figure's current screen location. Their<br />
types will be "IORef Point". These variables should be created in the figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that simulates a C++/Java-style interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you try to write a procedure that reads the contents of a file<br />
with a given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as a pure function will simplify the code that uses it, I<br />
agree. But this creates problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that procures this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating, it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is ruled by a value's necessity - the language computes only the values that a really required to calculate the final result. But what does this mean according to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What guarantees that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute the overall function<br />
result (that in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used. You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via "world" values.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' sugar we've seen above:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4633IO inside2006-07-04T03:29:39Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on global mutable variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value two times<br />
# even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return from 'getchar' an additional fake result that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating and throw it away! How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the too-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my program's modules is the memory suballocator. It<br />
receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside this procedure. Because the creation of these references is<br />
a part of the 'memoryAllocator' IO actions chain, a new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement a very simple memory allocator) are<br />
read and written in the 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description }<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description }<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables that holds the figure's current screen location. Their<br />
types will be "IORef Point". These variables should be created in the figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that simulates a C++/Java-style interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers coming from an imperative language background often look for a way to execute IO actions inside a pure procedure. But what does this mean?<br />
Imagine that you try to write a procedure that reads the contents of a file<br />
with a given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as a pure function will simplify the code that uses it, I<br />
agree. But this creates problems for the compiler:<br />
<br />
# This call is not inserted in a sequence of "world transformations", so the compiler doesn't know at what exact moment you want to execute this action. For example, if file has one kind of contents at the beginning of the program and another at the end - which contents do you want to see? You have no idea when (or even if) this function is going to get invoked, because Haskell sees this function as pure and feels free to reorder the execution of any or all pure functions as needed.<br />
# Attempts to read the contents of files with the same name can be factored (''i.e.'' reduced to a single call) despite the fact that the file (or the current directory) can be changed between calls. Again, Haskell considers all functions to be pure and feels free to omit multiple calls with the same parameters.<br />
<br />
So, implementing pure functions that interact with the Real World is<br />
considered to be Bad Behavior. Good boys and girls never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring the RealWorld "baton" in to call an IO action. Pure functions don't have the baton, but there is a special "magic" procedure that procures this baton from nowhere, uses it to call an IO action and then throws the resulting "world" away! It's a little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at its (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a, RealWorld)) -> a<br />
unsafePerformIO action = let (a, world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is an internal function producing a new value of<br />
the RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that do<br />
I/O inside. But don't do this without a real need, and remember to<br />
follow this rule: the compiler doesn't know that you are cheating, it still<br />
considers each non-IO function to be a pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to its execution. So<br />
you must ensure that:<br />
<br />
# The result of each call depends only on its arguments.<br />
# You don't rely on side-effects of this function, which may be not executed if its results are not needed.<br />
<br />
<br />
Let's investigate this problem more deeply. Function evaluation in Haskell<br />
is ruled by a value's necessity - the language computes only the values that a really required to calculate the final result. But what does this mean according to the 'main' function? To "calculate the final world's" value, you need to perform all the intermediate IO actions that are included in the 'main' chain. By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What guarantees that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute the overall function<br />
result (that in turn should be required to perform some action in the<br />
'main' chain). This is an example of Haskell's evaluation-by-need strategy. Now you should clearly see the difference:<br />
<br />
- An IO action inside an IO procedure is guaranteed to execute as long as<br />
it is (directly or indirectly) inside the 'main' chain - even when its result isn't used. You directly specify the order of the action's execution inside the IO procedure. Data dependencies are simulated via "world" values.<br />
<br />
- An IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. The evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
whatever data dependencies may exist).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with the help of the same binding<br />
operators and/or 'do' sugar we've seen above:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as the result of the 'unsafePerformIO' call is needed. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates the "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
(The 'seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is an even stranger operation called 'unsafeInterleaveIO' that<br />
gets the "official baton", makes its own pirate copy, and then runs<br />
an "illegal" relay-race in parallel with the main one! I can't talk further<br />
about its behavior without causing grief and indignation, so it's no surprise<br />
that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don't even ask me - I won't say anything more about this dirty trick I use all the time ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4632IO inside2006-07-04T03:08:55Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on global mutable variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value two times<br />
# even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return from 'getchar' an additional fake result that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating and throw it away! How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the too-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my program's modules is the memory suballocator. It<br />
receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside this procedure. Because the creation of these references is<br />
a part of the 'memoryAllocator' IO actions chain, a new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement a very simple memory allocator) are<br />
read and written in the 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record types ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create a heterogeneous list of figures. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of a "class" let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
The constructor of each figure's type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with a simplified implementation of the 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description}<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description}<br />
</haskell><br />
<br />
<br />
As you see, each constructor just returns a fixed 'draw' procedure that prints<br />
parameters with which the concrete figure was created. Let's test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's define "full-featured" figures that can actually be<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables that holds the figure's current screen location. Their<br />
types will be "IORef Point". These variables should be created in the figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
the Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
It's important to realize that we are not limited to including only IO actions<br />
in a record that simulates a C++/Java-style interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers with imperative background often still looks for a ways to<br />
execute IO actions inside the pure procedures. But that this means?<br />
Imagine that you try to write procedure that reads contents of file<br />
with given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as pure function will simplify the code that use it, i<br />
agree. But this creates troubles for the compiler:<br />
<br />
# This call is not inserted in sequence of "world transformations", so compiler don't get a hint - at what exact moment you want to execute this action. For example, if file contents is one at the program start and another at the end - what contents you want to see? Moment of "consumption" of this value don't make strong guarantees for execution order, because Haskell see all the functions as pure and fell free to reorder their execution as needed.<br />
# Attempts to read contents of file with the same name can be factorized despite the fact that file (or current directory) can be changed between calls. Again, Haskell looks at all the functions as pure ones and feel free to omit excessive calls with the same parameters.<br />
<br />
So, implementing functions that interacts with Real World as pure ones<br />
considered as a Bad Behavior. Good boys never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring "baton" to call IO action. Pure function don't have the baton,<br />
but there is special procedure, that procures this baton from nowhere,<br />
uses it to call IO action and then throws resulting "world" away!<br />
A little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at it's (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a,RealWorld)) -> a<br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is internal function producing new value of<br />
RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that does<br />
I/O inside. But don't do this without real need, and remember to<br />
follow this rule: compiler don't know that you are cheating, it still<br />
consider each non-IO function as pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to it's execution. So<br />
you must ensure that:<br />
<br />
# Result of each call depends only on it's arguments<br />
# You don't rely on side-effects of this function, which may be not executed if it's results are not used<br />
<br />
<br />
Let's investigate this problem deeper. Function evaluation in Haskell<br />
are ruled by value's necessity - computed only the values that really<br />
required to calculate final result. But that this means according to<br />
'main' function? To "calculate final world's" value, it's required to<br />
perform all the intermediate IO actions that included in 'main' chain.<br />
By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What can guarantee that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute overall function<br />
result (that in turn should be required to perform some action in<br />
'main' chain). Here we return to the Haskell-natural<br />
evaluation-on-value-need. Now you should clearly see the difference:<br />
<br />
- IO action inside IO procedure guaranteed to execute as long as<br />
it is inside 'main' chain - even when it's result is not used.<br />
You directly specify order of action's execution inside IO procedure.<br />
Data dependencies are simulated via "world" values.<br />
<br />
- IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. Evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
data dependency).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with help of the same binding<br />
operators and/or 'do' sugar:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as 'unsafePerformIO' result will be demanded. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
('seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is even more strange operation - 'unsafeInterleaveIO' that<br />
gets "official baton", makes it's piratical copy, and then run's<br />
"illegal" relay-race in parallel with main one! I can't further say<br />
about it's behavior without grief and indignation, it's not surprise<br />
that this operation is widely used in such software-piratical<br />
countries as Russia and China! ;) Don't even ask me - i will say<br />
nothing about this dirty trick i using permanently ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4631IO inside2006-07-04T02:59:24Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on global mutable variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value two times<br />
# even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return from 'getchar' an additional fake result that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating and throw it away! How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the too-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: a memory allocator generator ===<br />
<br />
As an example, one of my program's modules is the memory suballocator. It<br />
receives the address and size of a large memory block and returns two<br />
procedures - one to allocate a subblock of a given size and the other to<br />
free the allocated subblock:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' work with references<br />
created inside this procedure. Because the creation of these references is<br />
a part of the 'memoryAllocator' IO actions chain, a new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement a very simple memory allocator) are<br />
read and written in the 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that use state<br />
available at the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite Haskell's lack<br />
of direct support for impure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record type ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create heterogeneous figures list. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of class let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
Constructor of each figures' type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with simplified implementation of 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description}<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description}<br />
</haskell><br />
<br />
<br />
As you see, they just returns fixed 'draw' procedure that prints<br />
parameters with which this concrete figure was created. Let's go to<br />
test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's go to define "full-featured" figures that can be really<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables what holds it's current screen location. Their<br />
type will be "IORef Point". These variables should be created in figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Let's pay attention that we are not limited to include only IO actions<br />
in the record that simulates C++/Java interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers with imperative background often still looks for a ways to<br />
execute IO actions inside the pure procedures. But that this means?<br />
Imagine that you try to write procedure that reads contents of file<br />
with given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as pure function will simplify the code that use it, i<br />
agree. But this creates troubles for the compiler:<br />
<br />
# This call is not inserted in sequence of "world transformations", so compiler don't get a hint - at what exact moment you want to execute this action. For example, if file contents is one at the program start and another at the end - what contents you want to see? Moment of "consumption" of this value don't make strong guarantees for execution order, because Haskell see all the functions as pure and fell free to reorder their execution as needed.<br />
# Attempts to read contents of file with the same name can be factorized despite the fact that file (or current directory) can be changed between calls. Again, Haskell looks at all the functions as pure ones and feel free to omit excessive calls with the same parameters.<br />
<br />
So, implementing functions that interacts with Real World as pure ones<br />
considered as a Bad Behavior. Good boys never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring "baton" to call IO action. Pure function don't have the baton,<br />
but there is special procedure, that procures this baton from nowhere,<br />
uses it to call IO action and then throws resulting "world" away!<br />
A little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at it's (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a,RealWorld)) -> a<br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is internal function producing new value of<br />
RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that does<br />
I/O inside. But don't do this without real need, and remember to<br />
follow this rule: compiler don't know that you are cheating, it still<br />
consider each non-IO function as pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to it's execution. So<br />
you must ensure that:<br />
<br />
# Result of each call depends only on it's arguments<br />
# You don't rely on side-effects of this function, which may be not executed if it's results are not used<br />
<br />
<br />
Let's investigate this problem deeper. Function evaluation in Haskell<br />
are ruled by value's necessity - computed only the values that really<br />
required to calculate final result. But that this means according to<br />
'main' function? To "calculate final world's" value, it's required to<br />
perform all the intermediate IO actions that included in 'main' chain.<br />
By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What can guarantee that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute overall function<br />
result (that in turn should be required to perform some action in<br />
'main' chain). Here we return to the Haskell-natural<br />
evaluation-on-value-need. Now you should clearly see the difference:<br />
<br />
- IO action inside IO procedure guaranteed to execute as long as<br />
it is inside 'main' chain - even when it's result is not used.<br />
You directly specify order of action's execution inside IO procedure.<br />
Data dependencies are simulated via "world" values.<br />
<br />
- IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. Evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
data dependency).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with help of the same binding<br />
operators and/or 'do' sugar:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as 'unsafePerformIO' result will be demanded. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
('seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is even more strange operation - 'unsafeInterleaveIO' that<br />
gets "official baton", makes it's piratical copy, and then run's<br />
"illegal" relay-race in parallel with main one! I can't further say<br />
about it's behavior without grief and indignation, it's not surprise<br />
that this operation is widely used in such software-piratical<br />
countries as Russia and China! ;) Don't even ask me - i will say<br />
nothing about this dirty trick i using permanently ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4630IO inside2006-07-04T02:53:48Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on global mutable variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value two times<br />
# even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return from 'getchar' an additional fake result that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating and throw it away! How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the too-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning an IO action as the function result? Well, we've done<br />
this each time we've defined an IO procedure - they all return IO actions<br />
that need a RealWorld value to be performed. While we usually just<br />
execute them as part of a higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we did in the example with 'get2chars'.<br />
<br />
But how about returning procedure a parameterized IO action from an IO procedure? Let's define a procedure that returns the i'th byte from a file represented as a Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So far so good. But how about a procedure that returns the i'th byte of a file<br />
with a given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens a file and returns...<br />
another IO procedure that will read the specified byte. But we can go<br />
further and include the 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? It may be better. But why do we add 'h' as a parameter to 'readi' if it can be obtained from the environment where 'readi' is now defined? A shorter version would be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What have we done here? We've build a parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in the following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more IO actions that you need,<br />
with or without parameters, possibly involving the parameters that your<br />
"constructor" received, and return them to the caller. Then these IO actions<br />
can be used in the rest of the program without any knowledge about your<br />
internal implementation strategy. Actually, this is used to<br />
partially emulate the OOP (or more precisely, the ADT) programming paradigm.<br />
<br />
<br />
=== Example: memory allocators generator ===<br />
<br />
For example, one of my program's modules is the memory suballocator. It<br />
receives address and size of large memory block and returns two<br />
procedures - one to allocate subblock of given size and second to<br />
return allocated block back:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' works with references<br />
created inside this procedure. Because creation of these references is<br />
a part of 'memoryAllocator' IO actions chain, new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement very simple memory allocator) are<br />
read and written in 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that is using state<br />
available on the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite the Haskell's lack<br />
of direct support for non-pure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record type ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create heterogeneous figures list. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of class let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
Constructor of each figures' type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with simplified implementation of 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description}<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description}<br />
</haskell><br />
<br />
<br />
As you see, they just returns fixed 'draw' procedure that prints<br />
parameters with which this concrete figure was created. Let's go to<br />
test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's go to define "full-featured" figures that can be really<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables what holds it's current screen location. Their<br />
type will be "IORef Point". These variables should be created in figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Let's pay attention that we are not limited to include only IO actions<br />
in the record that simulates C++/Java interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers with imperative background often still looks for a ways to<br />
execute IO actions inside the pure procedures. But that this means?<br />
Imagine that you try to write procedure that reads contents of file<br />
with given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as pure function will simplify the code that use it, i<br />
agree. But this creates troubles for the compiler:<br />
<br />
# This call is not inserted in sequence of "world transformations", so compiler don't get a hint - at what exact moment you want to execute this action. For example, if file contents is one at the program start and another at the end - what contents you want to see? Moment of "consumption" of this value don't make strong guarantees for execution order, because Haskell see all the functions as pure and fell free to reorder their execution as needed.<br />
# Attempts to read contents of file with the same name can be factorized despite the fact that file (or current directory) can be changed between calls. Again, Haskell looks at all the functions as pure ones and feel free to omit excessive calls with the same parameters.<br />
<br />
So, implementing functions that interacts with Real World as pure ones<br />
considered as a Bad Behavior. Good boys never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring "baton" to call IO action. Pure function don't have the baton,<br />
but there is special procedure, that procures this baton from nowhere,<br />
uses it to call IO action and then throws resulting "world" away!<br />
A little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at it's (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a,RealWorld)) -> a<br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is internal function producing new value of<br />
RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that does<br />
I/O inside. But don't do this without real need, and remember to<br />
follow this rule: compiler don't know that you are cheating, it still<br />
consider each non-IO function as pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to it's execution. So<br />
you must ensure that:<br />
<br />
# Result of each call depends only on it's arguments<br />
# You don't rely on side-effects of this function, which may be not executed if it's results are not used<br />
<br />
<br />
Let's investigate this problem deeper. Function evaluation in Haskell<br />
are ruled by value's necessity - computed only the values that really<br />
required to calculate final result. But that this means according to<br />
'main' function? To "calculate final world's" value, it's required to<br />
perform all the intermediate IO actions that included in 'main' chain.<br />
By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What can guarantee that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute overall function<br />
result (that in turn should be required to perform some action in<br />
'main' chain). Here we return to the Haskell-natural<br />
evaluation-on-value-need. Now you should clearly see the difference:<br />
<br />
- IO action inside IO procedure guaranteed to execute as long as<br />
it is inside 'main' chain - even when it's result is not used.<br />
You directly specify order of action's execution inside IO procedure.<br />
Data dependencies are simulated via "world" values.<br />
<br />
- IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. Evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
data dependency).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with help of the same binding<br />
operators and/or 'do' sugar:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as 'unsafePerformIO' result will be demanded. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
('seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is even more strange operation - 'unsafeInterleaveIO' that<br />
gets "official baton", makes it's piratical copy, and then run's<br />
"illegal" relay-race in parallel with main one! I can't further say<br />
about it's behavior without grief and indignation, it's not surprise<br />
that this operation is widely used in such software-piratical<br />
countries as Russia and China! ;) Don't even ask me - i will say<br />
nothing about this dirty trick i using permanently ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4629IO inside2006-07-04T02:45:53Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on global mutable variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value two times<br />
# even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return from 'getchar' an additional fake result that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating and throw it away! How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the too-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: a list of IO actions ===<br />
<br />
Let's try defining a list of IO actions:<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't believe that these actions will<br />
not be executed immediately, just recall the real type of this list:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, right? :) Really, any IO action that you write in the 'do'<br />
statement (or use as a parameter for the '>>'/'>>=' operators) is an expression<br />
returning a result of type 'IO a' for some type 'a'. Typically, you use some function that has the type 'x -> y -> ... -> IO a' and provide all the x, y, etc. parameters. But you're not limited to this standard scenario -<br />
don't forget that Haskell is a functional language and you're free to<br />
compute the functional value required (recall that 'IO a' is really a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in the previous example - that's also<br />
OK. Want to see this functional value passed as the parameter?<br />
Just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions just like we can with any other functional values! For example, let's define a function that executes all the IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extract IO actions from the list and insert<br />
them into a chain of IO operations that should be performed to "compute<br />
the final world value" of the entire 'sequence_' call.<br />
<br />
With the help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of arbitrary complexity. Try, for example, to define a control<br />
structure that repeats an action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning an IO action as a result ===<br />
<br />
How about returning IO action as the function result? Well, we done<br />
this each time we defined IO procedure - they all return IO action<br />
that need RealWorld value to be performed. While we most times just<br />
executed them in chain of higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we done in example with 'get2chars'.<br />
<br />
But how about returning from IO procedure a parameterized IO action?<br />
Let's define a procedure that returns i'th byte from file represented<br />
as Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So bad so good. But how about procedure that returns i'th byte of file<br />
with given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens file and returns...<br />
another IO procedure that will read byte specified. But we can go<br />
further and include 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? May be better. Why we add 'h' as 'readi' parameter if it can be<br />
got from the environment where 'readi' now defined? Shorter will be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What we've done here? We've build parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more (using tuple) IO actions that your need,<br />
with and/or without parameters, involving the parameters that your<br />
"constructor" received, and return them to caller. Then these IO actions<br />
can be used in rest of program without any knowledge about your<br />
internal implementation strategies. Actually, this is used to<br />
partially emulate OOP (to be exact, ADT) programming ideology.<br />
<br />
<br />
=== Example: memory allocators generator ===<br />
<br />
For example, one of my program's modules is the memory suballocator. It<br />
receives address and size of large memory block and returns two<br />
procedures - one to allocate subblock of given size and second to<br />
return allocated block back:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' works with references<br />
created inside this procedure. Because creation of these references is<br />
a part of 'memoryAllocator' IO actions chain, new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement very simple memory allocator) are<br />
read and written in 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that is using state<br />
available on the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite the Haskell's lack<br />
of direct support for non-pure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record type ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create heterogeneous figures list. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of class let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
Constructor of each figures' type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with simplified implementation of 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description}<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description}<br />
</haskell><br />
<br />
<br />
As you see, they just returns fixed 'draw' procedure that prints<br />
parameters with which this concrete figure was created. Let's go to<br />
test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's go to define "full-featured" figures that can be really<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables what holds it's current screen location. Their<br />
type will be "IORef Point". These variables should be created in figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Let's pay attention that we are not limited to include only IO actions<br />
in the record that simulates C++/Java interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers with imperative background often still looks for a ways to<br />
execute IO actions inside the pure procedures. But that this means?<br />
Imagine that you try to write procedure that reads contents of file<br />
with given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as pure function will simplify the code that use it, i<br />
agree. But this creates troubles for the compiler:<br />
<br />
# This call is not inserted in sequence of "world transformations", so compiler don't get a hint - at what exact moment you want to execute this action. For example, if file contents is one at the program start and another at the end - what contents you want to see? Moment of "consumption" of this value don't make strong guarantees for execution order, because Haskell see all the functions as pure and fell free to reorder their execution as needed.<br />
# Attempts to read contents of file with the same name can be factorized despite the fact that file (or current directory) can be changed between calls. Again, Haskell looks at all the functions as pure ones and feel free to omit excessive calls with the same parameters.<br />
<br />
So, implementing functions that interacts with Real World as pure ones<br />
considered as a Bad Behavior. Good boys never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring "baton" to call IO action. Pure function don't have the baton,<br />
but there is special procedure, that procures this baton from nowhere,<br />
uses it to call IO action and then throws resulting "world" away!<br />
A little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at it's (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a,RealWorld)) -> a<br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is internal function producing new value of<br />
RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that does<br />
I/O inside. But don't do this without real need, and remember to<br />
follow this rule: compiler don't know that you are cheating, it still<br />
consider each non-IO function as pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to it's execution. So<br />
you must ensure that:<br />
<br />
# Result of each call depends only on it's arguments<br />
# You don't rely on side-effects of this function, which may be not executed if it's results are not used<br />
<br />
<br />
Let's investigate this problem deeper. Function evaluation in Haskell<br />
are ruled by value's necessity - computed only the values that really<br />
required to calculate final result. But that this means according to<br />
'main' function? To "calculate final world's" value, it's required to<br />
perform all the intermediate IO actions that included in 'main' chain.<br />
By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What can guarantee that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute overall function<br />
result (that in turn should be required to perform some action in<br />
'main' chain). Here we return to the Haskell-natural<br />
evaluation-on-value-need. Now you should clearly see the difference:<br />
<br />
- IO action inside IO procedure guaranteed to execute as long as<br />
it is inside 'main' chain - even when it's result is not used.<br />
You directly specify order of action's execution inside IO procedure.<br />
Data dependencies are simulated via "world" values.<br />
<br />
- IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. Evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
data dependency).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with help of the same binding<br />
operators and/or 'do' sugar:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as 'unsafePerformIO' result will be demanded. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
('seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is even more strange operation - 'unsafeInterleaveIO' that<br />
gets "official baton", makes it's piratical copy, and then run's<br />
"illegal" relay-race in parallel with main one! I can't further say<br />
about it's behavior without grief and indignation, it's not surprise<br />
that this operation is widely used in such software-piratical<br />
countries as Russia and China! ;) Don't even ask me - i will say<br />
nothing about this dirty trick i using permanently ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4614IO inside2006-07-03T07:38:57Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on global mutable variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value two times<br />
# even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return from 'getchar' an additional fake result that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating and throw it away! How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the too-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
By this point you should understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton"; they don't know any "world" value to pass to an IO action.<br />
The RealWorld type is an abstract datatype, so pure functions also can't construct RealWorld values by themselves, and it's a strict type, so 'undefined' also can't be used. So, the prohibition of using IO actions inside pure procedures is just a type system trick as it usually is in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But an IO action will remain a<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in its "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of the process of<br />
"calculating the final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main world0 = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind a value to 'get2chars' and then write a binding<br />
involving 'putStr'. But what's the execution order? It's not defined<br />
by the order of writing bindings, it's defined by the order of processing<br />
"world" values! You can arbitrarily reorder the binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that isn't included in the IO chain, is<br />
translated just to the 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' doesn't have any<br />
impact on the evaluation order, which is defined by the order of passing<br />
"world" values that is, in turn, defined by the order of the ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like 'get2chars' can't be executed directly<br />
because they are functions with a RealWorld parameter. To execute them,<br />
we need to supply the RealWorld parameter, i.e. insert them in the 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will remain like any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass them as function parameters and return them as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: list of IO actions ===<br />
<br />
Let's try. How about defining list of IO actions?<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't belive that these actions will<br />
not be executed until your command, just uncover this list type:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, yeah? :) Really, any IO action you write in the 'do'<br />
statement (or use as parameter for '>>'/'>>=') is an expression<br />
returning result of type "IO a". Typically, you use some function that<br />
has type "x -> y -> ... -> IO a" and provide all these x, y and<br />
so on parameters. But you are not limited to this standard scenario -<br />
don't forget that Haskell is functional language and you are free to<br />
compute the functional value required (recall - "IO a" is a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in previous example - it's also<br />
ok. Want to see this functional value passed as the parameter - heh,<br />
just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions as any other functional values! For example, let's<br />
define function that executes all IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extracts IO actions from the list and inserts<br />
them into chain of IO operations that should be performed to "compute<br />
final world value" of entire 'sequence_' call.<br />
<br />
With help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of any complexity. Try, for example, to define control<br />
structure that repeats the action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning IO action as a result ===<br />
<br />
How about returning IO action as the function result? Well, we done<br />
this each time we defined IO procedure - they all return IO action<br />
that need RealWorld value to be performed. While we most times just<br />
executed them in chain of higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we done in example with 'get2chars'.<br />
<br />
But how about returning from IO procedure a parameterized IO action?<br />
Let's define a procedure that returns i'th byte from file represented<br />
as Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So bad so good. But how about procedure that returns i'th byte of file<br />
with given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens file and returns...<br />
another IO procedure that will read byte specified. But we can go<br />
further and include 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? May be better. Why we add 'h' as 'readi' parameter if it can be<br />
got from the environment where 'readi' now defined? Shorter will be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What we've done here? We've build parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more (using tuple) IO actions that your need,<br />
with and/or without parameters, involving the parameters that your<br />
"constructor" received, and return them to caller. Then these IO actions<br />
can be used in rest of program without any knowledge about your<br />
internal implementation strategies. Actually, this is used to<br />
partially emulate OOP (to be exact, ADT) programming ideology.<br />
<br />
<br />
=== Example: memory allocators generator ===<br />
<br />
For example, one of my program's modules is the memory suballocator. It<br />
receives address and size of large memory block and returns two<br />
procedures - one to allocate subblock of given size and second to<br />
return allocated block back:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' works with references<br />
created inside this procedure. Because creation of these references is<br />
a part of 'memoryAllocator' IO actions chain, new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement very simple memory allocator) are<br />
read and written in 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that is using state<br />
available on the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite the Haskell's lack<br />
of direct support for non-pure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record type ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create heterogeneous figures list. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of class let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
Constructor of each figures' type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with simplified implementation of 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description}<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description}<br />
</haskell><br />
<br />
<br />
As you see, they just returns fixed 'draw' procedure that prints<br />
parameters with which this concrete figure was created. Let's go to<br />
test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's go to define "full-featured" figures that can be really<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables what holds it's current screen location. Their<br />
type will be "IORef Point". These variables should be created in figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Let's pay attention that we are not limited to include only IO actions<br />
in the record that simulates C++/Java interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers with imperative background often still looks for a ways to<br />
execute IO actions inside the pure procedures. But that this means?<br />
Imagine that you try to write procedure that reads contents of file<br />
with given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as pure function will simplify the code that use it, i<br />
agree. But this creates troubles for the compiler:<br />
<br />
# This call is not inserted in sequence of "world transformations", so compiler don't get a hint - at what exact moment you want to execute this action. For example, if file contents is one at the program start and another at the end - what contents you want to see? Moment of "consumption" of this value don't make strong guarantees for execution order, because Haskell see all the functions as pure and fell free to reorder their execution as needed.<br />
# Attempts to read contents of file with the same name can be factorized despite the fact that file (or current directory) can be changed between calls. Again, Haskell looks at all the functions as pure ones and feel free to omit excessive calls with the same parameters.<br />
<br />
So, implementing functions that interacts with Real World as pure ones<br />
considered as a Bad Behavior. Good boys never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring "baton" to call IO action. Pure function don't have the baton,<br />
but there is special procedure, that procures this baton from nowhere,<br />
uses it to call IO action and then throws resulting "world" away!<br />
A little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at it's (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a,RealWorld)) -> a<br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is internal function producing new value of<br />
RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that does<br />
I/O inside. But don't do this without real need, and remember to<br />
follow this rule: compiler don't know that you are cheating, it still<br />
consider each non-IO function as pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to it's execution. So<br />
you must ensure that:<br />
<br />
# Result of each call depends only on it's arguments<br />
# You don't rely on side-effects of this function, which may be not executed if it's results are not used<br />
<br />
<br />
Let's investigate this problem deeper. Function evaluation in Haskell<br />
are ruled by value's necessity - computed only the values that really<br />
required to calculate final result. But that this means according to<br />
'main' function? To "calculate final world's" value, it's required to<br />
perform all the intermediate IO actions that included in 'main' chain.<br />
By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What can guarantee that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute overall function<br />
result (that in turn should be required to perform some action in<br />
'main' chain). Here we return to the Haskell-natural<br />
evaluation-on-value-need. Now you should clearly see the difference:<br />
<br />
- IO action inside IO procedure guaranteed to execute as long as<br />
it is inside 'main' chain - even when it's result is not used.<br />
You directly specify order of action's execution inside IO procedure.<br />
Data dependencies are simulated via "world" values.<br />
<br />
- IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. Evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
data dependency).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with help of the same binding<br />
operators and/or 'do' sugar:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as 'unsafePerformIO' result will be demanded. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
('seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is even more strange operation - 'unsafeInterleaveIO' that<br />
gets "official baton", makes it's piratical copy, and then run's<br />
"illegal" relay-race in parallel with main one! I can't further say<br />
about it's behavior without grief and indignation, it's not surprise<br />
that this operation is widely used in such software-piratical<br />
countries as Russia and China! ;) Don't even ask me - i will say<br />
nothing about this dirty trick i using permanently ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also haven't said anything about exception handling,<br />
which is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4613IO inside2006-07-03T07:25:05Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on global mutable variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value two times<br />
# even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return from 'getchar' an additional fake result that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating and throw it away! How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the too-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br />
# the result of the "same" action (such as "readVariable varA") will not be reused<br />
<br />
So, the code above really should be written as:<br />
<br />
<haskell><br />
main = do varA <- newIORef 0 -- Create and initialize a new variable<br />
a0 <- readIORef varA<br />
writeIORef varA 1<br />
a1 <- readIORef varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Here, 'varA' has the type "IORef Int" which means "a variable (reference) in<br />
the IO monad holding a value of type Int". newIORef creates a new variable<br />
(reference) and returns it, and then read/write actions use this<br />
reference. The value returned by the "readIORef varA" action may depend not<br />
only on the variable involved but also on the moment of performing this<br />
operation so it can return different values on each call.<br />
<br />
Arrays, hash tables and any other _mutable_ data structures are<br />
defined in the same way - for each of them, there's an operation that creates new "mutable values" and returns a reference to it. Then special read and write<br />
operations in the IO monad are used. The following code shows an example<br />
of using mutable arrays:<br />
<br />
<haskell><br />
import Data.Array.IO<br />
main = do arr <- newArray (1,10) 37 :: IO (IOArray Int Int)<br />
a <- readArray arr 1<br />
writeArray arr 1 64<br />
b <- readArray arr 1<br />
print (a,b)<br />
</haskell><br />
<br />
Here, an array of 10 elements with 37 as the initial value at each location is created. After reading the value of the first element (index 1) to 'a' this element's value is changed to 64 and then read again to 'b'. As you can see by executing this code, 'a' will be set to 37 and 'b' to 64.<br />
<br />
<br />
<br />
Other state-dependent operations are also often implemented as IO<br />
actions. For example, a random number generator should return a different<br />
value on each call. It looks natural to give it a type involving IO:<br />
<br />
<haskell><br />
rand :: IO Int<br />
</haskell><br />
<br />
Moreover, when you import C routines you should be careful - if this<br />
routine is impure, i.e. its result depends on something in the "real<br />
world" (file system, memory contents...), internal state and so on,<br />
you should give it an IO type. Otherwise, the compiler can<br />
"optimize" repetitive calls of this procedure with the same parameters! :)<br />
<br />
For example, we can write a non-IO type for:<br />
<br />
<haskell><br />
foreign import ccall<br />
sin :: Double -> Double<br />
</haskell><br />
<br />
because the result of 'sin' depends only on its argument, but<br />
<br />
<haskell><br />
foreign import ccall<br />
tell :: Int -> IO Int<br />
</haskell><br />
<br />
If you will declare 'tell' as a pure function (without IO) then you may<br />
get the same position on each call! :)<br />
<br />
== IO actions as values ==<br />
<br />
Now you should precisely understand why it's impossible to use IO<br />
actions inside non-IO (pure) procedures. Such procedures just don't<br />
get a "baton", don't know any "world" value to pass to IO action.<br />
RealWorld is abstract datatype, so they also can't construct it's<br />
values by himself, and it's a strict type, so 'undefined' also can't<br />
be used. So, prohibition of using IO actions inside pure procedures is<br />
just a type trick as it is usual in Haskell :)<br />
<br />
But while pure code can't _execute_ IO actions, it can work with them<br />
as with any other functional values - they can be stored in data<br />
structures, passed as parameters and returned as results, collected in<br />
lists, and partially applied. But anyway IO action will remain<br />
functional value because we can't apply it to the last argument - of<br />
type RealWorld.<br />
<br />
In order to _execute_ the IO action we need to apply it to some<br />
RealWorld value that can be done only inside some IO procedure,<br />
in it's "actions chain". And real execution of this action will take<br />
place only when this procedure is called as part of process of<br />
"calculating final value of world" for 'main'. Look at this example:<br />
<br />
<haskell><br />
main = let get2chars = getChar >> getChar<br />
((), world1) = putStr "Press two keys" world0<br />
(answer, world2) = get2chars world1<br />
in ((), world2)<br />
</haskell><br />
<br />
Here we first bind value to 'get2chars' and then write binding<br />
involving 'putStr'. But what is an execution order? It is not defined<br />
by order of writing bindings, it is defined by order of processing<br />
"world" values! You can arbitrarily reorder binding statements - in<br />
any case execution order will be defined by dependence on passing<br />
"world" values. Let's see how this 'main' looks in the 'do' notation:<br />
<br />
<haskell><br />
main = do let get2chars = getChar >> getChar<br />
putStr "Press two keys"<br />
get2chars<br />
return ()<br />
</haskell><br />
<br />
As you can see, the 'let' binding that is not included in IO chain, is<br />
translated just to 'let' statement inside the 'do' sequence. And as<br />
you now should understand, placement of this 'let' don't has any<br />
impact on the evaluation order, which is defined by order of passing<br />
"world" values that is, in turn, defined by order of ordinal (non-let)<br />
statements inside 'do'!<br />
<br />
Moreover, IO actions like this 'get2chars' can't be executed just<br />
because they are functions with RealWorld parameter. To execute them,<br />
we should supply the RealWorld parameter, i.e. insert them in 'main'<br />
chain, placing them in some 'do' sequence executed from 'main'. Until<br />
that is done, they will be keep as any function, in partially<br />
evaluated form. And we can work with IO actions as with any other<br />
functions - bind them to names (like above), save them to data<br />
structures, pass as function parameters and return as results - and<br />
they will not be performed until you give them this magic RealWorld<br />
parameter!<br />
<br />
<br />
<br />
=== Example: list of IO actions ===<br />
<br />
Let's try. How about defining list of IO actions?<br />
<br />
<haskell><br />
ioActions :: [IO ()]<br />
ioActions = [(print "Hello!"),<br />
(putStr "just kidding"),<br />
(getChar >> return ())<br />
]<br />
</haskell><br />
<br />
I used additional parentheses around each action, although they are<br />
not really required. If you still can't belive that these actions will<br />
not be executed until your command, just uncover this list type:<br />
<br />
<haskell><br />
ioActions :: [RealWorld -> ((), RealWorld)]<br />
</haskell><br />
<br />
Well, now we want to execute some of these actions. No problem, just<br />
insert them into the 'main' chain:<br />
<br />
<haskell><br />
main = do head ioActions<br />
ioActions !! 1<br />
last ioActions<br />
</haskell><br />
<br />
Looks strange, yeah? :) Really, any IO action you write in the 'do'<br />
statement (or use as parameter for '>>'/'>>=') is an expression<br />
returning result of type "IO a". Typically, you use some function that<br />
has type "x -> y -> ... -> IO a" and provide all these x, y and<br />
so on parameters. But you are not limited to this standard scenario -<br />
don't forget that Haskell is functional language and you are free to<br />
compute the functional value required (recall - "IO a" is a function<br />
type) in any possible way. Here we just extracted several functions<br />
from the list - no problem. This functional value can also be<br />
constructed on-the-fly, as we've done in previous example - it's also<br />
ok. Want to see this functional value passed as the parameter - heh,<br />
just look at the 'when' definition. Hey, we can sell, buy and rent<br />
these IO actions as any other functional values! For example, let's<br />
define function that executes all IO actions in the list:<br />
<br />
<haskell><br />
sequence_ :: [IO a] -> IO ()<br />
sequence_ [] = return ()<br />
sequence_ (x:xs) = do x<br />
sequence_ xs<br />
</haskell><br />
<br />
No black magic - we just extracts IO actions from the list and inserts<br />
them into chain of IO operations that should be performed to "compute<br />
final world value" of entire 'sequence_' call.<br />
<br />
With help of 'sequence_', we can rewrite our last 'main' as:<br />
<br />
<haskell><br />
main = sequence_ ioActions<br />
</haskell><br />
<br />
<br />
Haskell's ability to work with IO actions as with any other<br />
(functional and non-functional) values allows us to define control<br />
structures of any complexity. Try, for example, to define control<br />
structure that repeats the action until it returns the 'False' result:<br />
<br />
<haskell><br />
while :: IO Bool -> IO ()<br />
while action = ???<br />
</haskell><br />
<br />
<br />
<br />
=== Example: returning IO action as a result ===<br />
<br />
How about returning IO action as the function result? Well, we done<br />
this each time we defined IO procedure - they all return IO action<br />
that need RealWorld value to be performed. While we most times just<br />
executed them in chain of higher-level IO procedure, it's also<br />
possible to just collect them without actual execution:<br />
<br />
<haskell><br />
main = do let a = sequence ioActions<br />
b = when True getChar<br />
c = getChar >> getChar<br />
putStr "'let' statements are not executed!"<br />
</haskell><br />
<br />
These assigned IO procedures can be used as parameters to other<br />
procedures, or written to global variables, or processed in some other<br />
way, or just executed later, as we done in example with 'get2chars'.<br />
<br />
But how about returning from IO procedure a parameterized IO action?<br />
Let's define a procedure that returns i'th byte from file represented<br />
as Handle:<br />
<br />
<haskell><br />
readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
</haskell><br />
<br />
So bad so good. But how about procedure that returns i'th byte of file<br />
with given name without reopening it each time?<br />
<br />
<haskell><br />
readfilei :: String -> IO (Integer -> IO Char)<br />
readfilei name = do h <- openFile name ReadMode<br />
return (readi h)<br />
</haskell><br />
<br />
As you can see, it's an IO procedure that opens file and returns...<br />
another IO procedure that will read byte specified. But we can go<br />
further and include 'readi' body into 'readfilei':<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi h i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return (readi h)<br />
</haskell><br />
<br />
Good? May be better. Why we add 'h' as 'readi' parameter if it can be<br />
got from the environment where 'readi' now defined? Shorter will be:<br />
<br />
<haskell><br />
readfilei name = do h <- openFile name ReadMode<br />
let readi i = do hSeek h i AbsoluteSeek<br />
hGetChar h<br />
return readi<br />
</haskell><br />
<br />
What we've done here? We've build parameterized IO action involving local<br />
names inside 'readfilei' and returned it as the result. Now it can be<br />
used in following way:<br />
<br />
<haskell><br />
main = do myfile <- readfilei "test"<br />
a <- myfile 0<br />
b <- myfile 1<br />
print (a,b)<br />
</haskell><br />
<br />
<br />
Such usage of IO actions is very typical for Haskell programs - you<br />
just construct one or more (using tuple) IO actions that your need,<br />
with and/or without parameters, involving the parameters that your<br />
"constructor" received, and return them to caller. Then these IO actions<br />
can be used in rest of program without any knowledge about your<br />
internal implementation strategies. Actually, this is used to<br />
partially emulate OOP (to be exact, ADT) programming ideology.<br />
<br />
<br />
=== Example: memory allocators generator ===<br />
<br />
For example, one of my program's modules is the memory suballocator. It<br />
receives address and size of large memory block and returns two<br />
procedures - one to allocate subblock of given size and second to<br />
return allocated block back:<br />
<br />
<haskell><br />
memoryAllocator :: Ptr a -> Int -> IO (Int -> IO (Ptr b),<br />
Ptr c -> IO ())<br />
<br />
memoryAllocator buf size = do ......<br />
let alloc size = do ...<br />
...<br />
free ptr = do ...<br />
...<br />
return (alloc, free)<br />
</haskell><br />
<br />
How this is implemented? 'alloc' and 'free' works with references<br />
created inside this procedure. Because creation of these references is<br />
a part of 'memoryAllocator' IO actions chain, new independent set of<br />
references will be created for each memory block for which<br />
'memoryAllocator' is called:<br />
<br />
<haskell><br />
memoryAllocator buf size = do start <- newIORef buf<br />
end <- newIORef (buf `plusPtr` size)<br />
...<br />
</haskell><br />
<br />
These two references (we will implement very simple memory allocator) are<br />
read and written in 'alloc' and 'free' definitions:<br />
<br />
<haskell><br />
let alloc size = do addr <- readIORef start<br />
writeIORef start (addr `plusPtr` size)<br />
return addr<br />
<br />
let free ptr = do writeIORef start ptr<br />
</haskell><br />
<br />
What we've defined here is just a pair of closures that is using state<br />
available on the moment of their definition. As you can see, it's as<br />
easy as in any other functional language, despite the Haskell's lack<br />
of direct support for non-pure functions.<br />
<br />
The following example uses procedures, returned by memoryAllocator, to<br />
simultaneously allocate/free blocks in two independent memory buffers:<br />
<br />
<haskell><br />
main = do buf1 <- mallocBytes (2^16)<br />
buf2 <- mallocBytes (2^20)<br />
(alloc1, free1) <- memoryAllocator buf1 (2^16)<br />
(alloc2, free2) <- memoryAllocator buf2 (2^20)<br />
ptr11 <- alloc1 100<br />
ptr21 <- alloc2 1000<br />
free1 ptr11<br />
free2 ptr21<br />
ptr12 <- alloc1 100<br />
ptr22 <- alloc2 1000<br />
</haskell><br />
<br />
<br />
<br />
=== Example: emulating OOP with record type ===<br />
<br />
Let's implement the classical OOP example: drawing figures. There are<br />
figures of different types: circles, rectangles and so on. The task is<br />
to create heterogeneous figures list. All figures in this list should<br />
support the same set of operations: draw, move and so on. We will<br />
represent these operations as IO procedures. Instead of class let's<br />
define a structure containing implementations of all the procedures<br />
required:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO ()<br />
}<br />
<br />
type Displacement = (Int, Int) -- horizontal and vertical displacement in points<br />
</haskell><br />
<br />
<br />
Constructor of each figures' type should just return a Figure record:<br />
<br />
<haskell><br />
circle :: Point -> Radius -> IO Figure<br />
rectangle :: Point -> Point -> IO Figure<br />
<br />
type Point = (Int, Int) -- point coordinates<br />
type Radius = Int -- circle radius in points<br />
</haskell><br />
<br />
<br />
We will "draw" figures by just printing their current parameters.<br />
Let's start with simplified implementation of 'circle' and 'rectangle'<br />
constructors, without actual 'move' support:<br />
<br />
<haskell><br />
circle center radius = do<br />
let description = " Circle at "++show center++" with radius "++show radius<br />
return $ Figure { draw = putStrLn description}<br />
<br />
rectangle from to = do<br />
let description = " Rectangle "++show from++"-"++show to)<br />
return $ Figure { draw = putStrLn description}<br />
</haskell><br />
<br />
<br />
As you see, they just returns fixed 'draw' procedure that prints<br />
parameters with which this concrete figure was created. Let's go to<br />
test it:<br />
<br />
<haskell><br />
drawAll :: [Figure] -> IO ()<br />
drawAll figures = do putStrLn "Drawing figures:"<br />
mapM_ draw figures<br />
<br />
main = do figures <- sequence [circle (10,10) 5,<br />
circle (20,20) 3,<br />
rectangle (10,10) (20,20),<br />
rectangle (15,15) (40,40)]<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Now let's go to define "full-featured" figures that can be really<br />
moved around. In order to achieve this, we should provide each figure<br />
with mutable variables what holds it's current screen location. Their<br />
type will be "IORef Point". These variables should be created in figure<br />
constructor and manipulated in IO procedures (closures) enclosed in<br />
Figure record:<br />
<br />
<haskell><br />
circle center radius = do<br />
centerVar <- newIORef center<br />
<br />
let drawF = do center <- readIORef centerVar<br />
putStrLn (" Circle at "++show center<br />
++" with radius "++show radius)<br />
<br />
let moveF (addX,addY) = do (x,y) <- readIORef centerVar<br />
writeIORef centerVar (x+addX, y+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
<br />
<br />
rectangle from to = do<br />
fromVar <- newIORef from<br />
toVar <- newIORef to<br />
<br />
let drawF = do from <- readIORef fromVar<br />
to <- readIORef toVar<br />
putStrLn (" Rectangle "++show from++"-"++show to)<br />
<br />
let moveF (addX,addY) = do (fromX,fromY) <- readIORef fromVar<br />
(toX,toY) <- readIORef toVar<br />
writeIORef fromVar (fromX+addX, fromY+addY)<br />
writeIORef toVar (toX+addX, toY+addY)<br />
<br />
return $ Figure { draw=drawF, move=moveF }<br />
</haskell><br />
<br />
<br />
Now we can add moving figures around to our test:<br />
<br />
<haskell><br />
main = do figures <- sequence [circle (10,10) 5,<br />
rectangle (10,10) (20,20)]<br />
drawAll figures<br />
mapM_ (\fig -> move fig (10,10)) figures<br />
drawAll figures<br />
</haskell><br />
<br />
<br />
Let's pay attention that we are not limited to include only IO actions<br />
in the record that simulates C++/Java interface. The record can include<br />
values, IORefs, pure functions - in short, any type of data. For<br />
example, we can easily add to Figure interface fields for area and<br />
origin:<br />
<br />
<haskell><br />
data Figure = Figure { draw :: IO (),<br />
move :: Displacement -> IO (),<br />
area :: Double,<br />
origin :: IORef Point<br />
}<br />
</haskell><br />
<br />
<br />
<br />
== unsafePerformIO and unsafeInterleaveIO ==<br />
<br />
Programmers with imperative background often still looks for a ways to<br />
execute IO actions inside the pure procedures. But that this means?<br />
Imagine that you try to write procedure that reads contents of file<br />
with given name:<br />
<br />
<haskell><br />
readContents :: Filename -> String<br />
</haskell><br />
<br />
Defining it as pure function will simplify the code that use it, i<br />
agree. But this creates troubles for the compiler:<br />
<br />
# This call is not inserted in sequence of "world transformations", so compiler don't get a hint - at what exact moment you want to execute this action. For example, if file contents is one at the program start and another at the end - what contents you want to see? Moment of "consumption" of this value don't make strong guarantees for execution order, because Haskell see all the functions as pure and fell free to reorder their execution as needed.<br />
# Attempts to read contents of file with the same name can be factorized despite the fact that file (or current directory) can be changed between calls. Again, Haskell looks at all the functions as pure ones and feel free to omit excessive calls with the same parameters.<br />
<br />
So, implementing functions that interacts with Real World as pure ones<br />
considered as a Bad Behavior. Good boys never do it ;)<br />
<br />
<br />
Nevertheless, there are (semi-official) ways to use IO actions inside<br />
of pure functions. As you should remember this is prohibited by<br />
requiring "baton" to call IO action. Pure function don't have the baton,<br />
but there is special procedure, that procures this baton from nowhere,<br />
uses it to call IO action and then throws resulting "world" away!<br />
A little low-level magic :) This very special procedure is:<br />
<br />
<haskell><br />
unsafePerformIO :: IO a -> a<br />
</haskell><br />
<br />
Let's look at it's (possible) definition:<br />
<br />
<haskell><br />
unsafePerformIO :: (RealWorld -> (a,RealWorld)) -> a<br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in a<br />
</haskell><br />
<br />
where 'createNewWorld' is internal function producing new value of<br />
RealWorld type.<br />
<br />
Using unsafePerformIO, you can easily write pure functions that does<br />
I/O inside. But don't do this without real need, and remember to<br />
follow this rule: compiler don't know that you are cheating, it still<br />
consider each non-IO function as pure one. Therefore, all the usual<br />
optimization rules can (and will!) be applied to it's execution. So<br />
you must ensure that:<br />
<br />
# Result of each call depends only on it's arguments<br />
# You don't rely on side-effects of this function, which may be not executed if it's results are not used<br />
<br />
<br />
Let's investigate this problem deeper. Function evaluation in Haskell<br />
are ruled by value's necessity - computed only the values that really<br />
required to calculate final result. But that this means according to<br />
'main' function? To "calculate final world's" value, it's required to<br />
perform all the intermediate IO actions that included in 'main' chain.<br />
By using 'unsafePerformIO' we call IO actions outside of this chain.<br />
What can guarantee that they will be run? Nothing. The only case when<br />
they will be run is if that is required to compute overall function<br />
result (that in turn should be required to perform some action in<br />
'main' chain). Here we return to the Haskell-natural<br />
evaluation-on-value-need. Now you should clearly see the difference:<br />
<br />
- IO action inside IO procedure guaranteed to execute as long as<br />
it is inside 'main' chain - even when it's result is not used.<br />
You directly specify order of action's execution inside IO procedure.<br />
Data dependencies are simulated via "world" values.<br />
<br />
- IO action inside 'unsafePerformIO' will be performed only if<br />
result of this operation is really used. Evaluation order is not<br />
guaranteed and you should not rely on it (except when you sure about<br />
data dependency).<br />
<br />
<br />
I should also say that inside 'unsafePerformIO' call you can organize<br />
small internal chain of IO actions with help of the same binding<br />
operators and/or 'do' sugar:<br />
<br />
<haskell><br />
one = unsafePerformIO $ do var <- newIORef 0<br />
writeIORef var 1<br />
readIORef var<br />
</haskell><br />
<br />
and in this case ALL the operations in this chain will be performed as<br />
long as 'unsafePerformIO' result will be demanded. To ensure this,<br />
the actual 'unsafePerformIO' implementation evaluates "world" returned<br />
by the 'action':<br />
<br />
<haskell><br />
unsafePerformIO action = let (a,world1) = action createNewWorld<br />
in (world1 `seq` a)<br />
</haskell><br />
<br />
('seq' operation strictly evaluates it's first argument before<br />
returning the value of second one)<br />
<br />
<br />
<br />
But there is even more strange operation - 'unsafeInterleaveIO' that<br />
gets "official baton", makes it's piratical copy, and then run's<br />
"illegal" relay-race in parallel with main one! I can't further say<br />
about it's behavior without grief and indignation, it's not surprise<br />
that this operation is widely used in such software-piratical<br />
countries as Russia and China! ;) Don't even ask me - i will say<br />
nothing about this dirty trick i using permanently ;)<br />
<br />
<br />
<br />
== fixIO and 'mdo' ==<br />
<br />
== ST monad ==<br />
<br />
== Q monad ==<br />
<br />
== Welcome to the machine: the actual [[GHC]] implementation ==<br />
<br />
A little disclaimer: after all, I should say that I don't describe<br />
here what a monad is (I don't even know it myself) and my<br />
explanation shows only one _possible_ way to implement them in<br />
Haskell. For example, the hbc Haskell compiler implements monads via<br />
continuations. I also didn't say anything about exception handling<br />
that is a natural part of the "monad" concept. You can read the "All About<br />
Monads" guide to learn more about these topics.<br />
<br />
But there is good news: first, the monad understanding you've acquired<br />
will work with any implementation. You just can't work with RealWorld<br />
values directly.<br />
<br />
Second, the IO monad implementation described here is really used in the GHC,<br />
yhc/nhc (Hugs/jhc, too?) compilers. Here is the actual IO definition<br />
from the GHC sources:<br />
<br />
<haskell><br />
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))<br />
</haskell><br />
<br />
It uses the "State# RealWorld" type instead of our RealWorld, it uses the "(# #)" strict tuple for optimization, and it adds an IO data constructor<br />
around the type. Nevertheless, there are no significant changes from the standpoint of our explanation. Knowing the principle of "chaining" IO actions via fake "state of world" values, you can now easily understand and write low-level implementations of GHC I/O operations.<br />
<br />
<br />
=== The [[Yhc]]/nhc98 implementation ===<br />
<br />
<haskell><br />
data World = World<br />
newtype IO a = IO (World -> Either IOError a)<br />
</haskell><br />
<br />
This implementation makes the "World" disappear somewhat, and returns Either a<br />
result 'a', or if an error occurs then 'IOError'. The lack of the World on the<br />
right hand side of the function can only be done because the compiler knows<br />
special things about the IO type, and will not overoptimise it.<br />
<br />
<br />
== Further reading ==<br />
<br />
This tutorial is largely based on the Simon Peyton Jones' paper [http://research.microsoft.com/%7Esimonpj/Papers/marktoberdorf Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]. I hope that my tutorial improves his original explanation of the Haskell I/O system and brings it closer to the point of view of beginning Haskell programmers. But if you need to learn about concurrency, exceptions and FFI in Haskell/GHC, the original paper is the best source of information.<br />
<br />
You can find more information about concurrency, FFI, STM and exceptions at the [[GHC/Concurrency#Starting points]] page.<br />
<br />
The [[Arrays]] page contains exhaustive explanations about using mutable arrays.<br />
<br />
Look also at the [[Books and tutorials#Using Monads]] page, which contains tutorials and papers really describing these mysterious monads :)<br />
<br />
Do you have more questions? Ask in the [http://www.haskell.org/mailman/listinfo/haskell-cafe haskell-cafe mailing list].<br />
<br />
----</div>Mvanierhttps://wiki.haskell.org/index.php?title=IO_inside&diff=4612IO inside2006-07-03T07:17:07Z<p>Mvanier: </p>
<hr />
<div>Haskell I/O has always been a source of confusion and surprises for new Haskellers. While simple I/O code in Haskell looks very similar to its equivalents in imperative languages, attempts to write somewhat more complex code often result in a total mess. This is because Haskell I/O is really very different internally. Haskell is a pure language and even the I/O system can't break this purity.<br />
<br />
The following text is an attempt to explain the details of Haskell I/O implementations. This explanation should help you eventually master all the smart I/O tricks. Moreover, I've added a detailed explanation of various traps you might encounter along the way. After reading this text, you will receive a "Master of Haskell I/O" degree that is equal to a Bachelor in Computer Science and Mathematics, simultaneously :)<br />
<br />
If you are new to Haskell I/O you may prefer to start by reading the [[Introduction to IO]] page.<br />
<br />
<br />
== Haskell is a pure language ==<br />
<br />
Haskell is a pure language, which means that the result of any function call is fully determined by its arguments. Pseudo-functions like rand() or getchar() in C which return different results on each call, are simply impossible to write in Haskell. Moreover, Haskell functions can't have side effects, which means that they can't effect any changes to the "real world", like changing files, writing to the screen, printing, sending data over the network, and so on. These two restrictions together mean that any function<br />
call can be omitted, repeated, or replaced by the result of a previous call with the same parameters, and the language '''guarantees''' that all these rearrangements will not change the program result!<br />
<br />
Let's compare this to C: optimizing C compilers try to guess which functions have no side effects and don't depend on global mutable variables. If this guess is wrong, an optimization can change the program's semantics! To avoid this kind of disaster, C optimizers are conservative in their guesses or require hints from the programmer about the purity of functions.<br />
<br />
Compared to an optimizing C compiler, a Haskell compiler is a set of pure mathematical transformations. This results in much better high-level optimization facilities. Moreover, pure mathematical computations can be much more easily divided into several threads that may be executed in parallel, which is increasingly important in these days of multi-core CPUs. Finally, pure computations are less error-prone and easier to verify, which adds to Haskell's robustness and to the speed of program development using Haskell.<br />
<br />
This purity creates other problems: how we can do I/O or work with stateful algorithms and side effects in a pure language? This question has had many different solutions proposed in 18 years of Haskell development, though a solution based on '''''monads''''' is now the standard.<br />
<br />
<br />
<br />
== What is a monad? ==<br />
<br />
What is a monad? It's something from mathematical category theory, which I<br />
don't know anymore :) In order to understand how monads are used to<br />
solve the problem of I/O and side effects, you don't need to know it. It's<br />
enough to just know elementary mathematics, like I do :)<br />
<br />
Let's imagine that we want to implement in Haskell the well-known<br />
'getchar' function. What type should it have? Let's try:<br />
<br />
<haskell><br />
getchar :: Char<br />
<br />
get2chars = [getchar,getchar]<br />
</haskell><br />
<br />
What will we get with 'getchar' having just the 'Char' type? You can see<br />
all the possible problems in the definition of 'get2chars':<br />
<br />
# because the Haskell compiler treats all functions as pure (not having side effects), it can avoid "excessive" calls to 'getchar' and use one returned value two times<br />
# even if it does make two calls, there is no way to determine which call should be performed first. Do you want to return the two chars in the order in which they were read, or in the opposite order? Nothing in the definition of 'get2chars' answers this question.<br />
<br />
How can these problems be solved, from the programmer's viewpoint?<br />
Let's introduce a fake parameter of 'getchar' to make each call<br />
"different" from the compiler's point of view:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
<br />
get2chars = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
Right away, this solves the first problem mentioned above - now the<br />
compiler will make two calls because it sees them as having different<br />
parameters. The whole 'get2chars' function should also have a<br />
fake parameter, otherwise we will have the same problem calling it:<br />
<br />
<haskell><br />
getchar :: Int -> Char<br />
get2chars :: Int -> String<br />
<br />
get2chars _ = [getchar 1, getchar 2]<br />
</haskell><br />
<br />
<br />
Now we need to give the compiler some clue to determine which function it<br />
should call first. The Haskell language doesn't provide any way to express<br />
order of evaluation... except for data dependencies! How about adding an<br />
artificial data dependency which prevents evaluation of the second<br />
'getchar' before the first one? In order to achieve this, we will<br />
return from 'getchar' an additional fake result that will be used as a<br />
parameter for the next 'getchar' call:<br />
<br />
<haskell><br />
getchar :: Int -> (Char, Int)<br />
<br />
get2chars _ = [a,b] where (a,i) = getchar 1<br />
(b,_) = getchar i<br />
</haskell><br />
<br />
So far so good - now we can guarantee that 'a' is read before 'b'<br />
because reading 'b' needs the value ('i') that is returned by reading 'a'!<br />
<br />
We've added a fake parameter to 'get2chars' but the problem is that the<br />
Haskell compiler is too smart! It can believe that the external 'getchar'<br />
function is really dependent on its parameter but for 'get2chars' it<br />
will see that we're just cheating and throw it away! How can we fix this? How about passing this fake parameter to the 'getchar' function?! In this case<br />
the compiler can't guess that it is really unused :)<br />
<br />
<haskell><br />
get2chars i0 = [a,b] where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
<br />
And more - 'get2chars' has all the same purity problems as the 'getchar'<br />
function. If you need to call it two times, you need a way to describe<br />
the order of these calls. Look at:<br />
<br />
<haskell><br />
get4chars = [get2chars 1, get2chars 2] -- order of 'get2chars' calls isn't defined<br />
</haskell><br />
<br />
We already know how to deal with these problems - 'get2chars' should<br />
also return some fake value that can be used to order calls:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
<br />
get4chars i0 = (a++b) where (a,i1) = get2chars i0<br />
(b,i2) = get2chars i1<br />
</haskell><br />
<br />
<br />
But what's the fake value 'get2chars' should return? If we use some integer constant, the too-smart Haskell compiler will guess that we're cheating again :) What about returning the value returned by 'getchar'? See:<br />
<br />
<haskell><br />
get2chars :: Int -> (String, Int)<br />
get2chars i0 = ([a,b], i2) where (a,i1) = getchar i0<br />
(b,i2) = getchar i1<br />
</haskell><br />
<br />
Believe it or not, but we've just constructed the whole "monadic"<br />
Haskell I/O system.<br />
<br />
<br />
<br />
== Welcome to the RealWorld, baby :) ==<br />
<br />
The 'main' Haskell function has the type:<br />
<br />
<haskell><br />
main :: RealWorld -> ((), RealWorld)<br />
</haskell><br />
<br />
where 'RealWorld' is a fake type used instead of our Int. It's something<br />
like the baton passed in a relay race. When 'main' calls some IO function,<br />
it passes the "RealWorld" it received as a parameter. All IO functions have<br />
similar types involving RealWorld as a parameter and result. To be<br />
exact, "IO" is a type synonym defined in the following way:<br />
<br />
<haskell><br />
type IO a = RealWorld -> (a, RealWorld)<br />
</haskell><br />
<br />
So, 'main' just has type "IO ()", 'getChar' has type "IO Char" and so<br />
on. Let's look at 'main' calling 'getChar' two times:<br />
<br />
<haskell><br />
getChar :: RealWorld -> (Char, RealWorld)<br />
<br />
main :: RealWorld -> ((), RealWorld)<br />
main world0 = let (a, world1) = getChar world0<br />
(b, world2) = getChar world1<br />
in ((), world2)<br />
</haskell><br />
<br />
<br />
Look at this closely: 'main' passes to first 'getChar' the "world" it<br />
received. This 'getChar' returns some new value of type RealWorld,<br />
that is used in the next call. Finally, 'main' returns the "world" it got<br />
from the second 'getChar'.<br />
<br />
# Is it possible here to omit any call of 'getChar' if the Char it read is not used? No, because we need to return the "world" that is the result of the second 'getChar' and this in turn requires the "world" returned from the first 'getChar'.<br />
# Is it possible to reorder the 'getChar' calls? No: the second 'getChar' can't be called before the first one because it uses the "world" returned from the first call.<br />
# Is it possible to duplicate calls? In Haskell semantics - yes, but real compilers never duplicate work in such simple cases (otherwise, the programs generated will not have any speed guarantees).<br />
<br />
<br />
As we already said, RealWorld values are used like a baton which gets passed<br />
between all routines called by 'main' in strict order. Inside each<br />
routine called, RealWorld values are used in the same way. Overall, in<br />
order to "compute" the world to be returned from 'main', we should perform<br />
each IO procedure that is called from 'main', directly or indirectly.<br />
This means that each procedure inserted in the chain will be performed<br />
just at the moment (relative to the other IO actions) when we intended it<br />
to be called. Let's consider the following program:<br />
<br />
<haskell><br />
main = do a <- ask "What is your name?"<br />
b <- ask "How old are you?"<br />
return ()<br />
<br />
ask s = do putStr s<br />
readLn<br />
</haskell><br />
<br />
Now you have enough knowledge to rewrite it in a low-level way and<br />
check that each operation that should be performed will really be<br />
performed with the arguments it should have and in the order we expect.<br />
<br />
<br />
But what about conditional execution? No problem. Let's define the<br />
well-known 'when' operation:<br />
<br />
<haskell><br />
when :: Bool -> IO () -> IO ()<br />
when condition action world =<br />
if condition<br />
then action world<br />
else ((), world)<br />
</haskell><br />
<br />
As you can see, we can easily include or exclude from the execution chain<br />
IO procedures (actions) depending on the data values. If 'condition'<br />
will be False on the call of 'when', 'action' will never be called because<br />
real Haskell compilers, again, never call functions whose results<br />
are not required to calculate the final result (i.e., here, the final "world" value of 'main').<br />
<br />
Loops and more complex control structures can be implemented in<br />
the same way. Try it as an exercise!<br />
<br />
<br />
Finally you may want to know how much this passing of RealWorld<br />
values around the program costs. It's free! These fake values exist solely for the compiler while it analyzes and optimizes the code, but when it gets to assembly code generation, it "suddenly" realize that this type is like "()", so<br />
all these parameters and result values can be omitted from the final generated code. Isn't it beautiful? :)<br />
<br />
<br />
<br />
== '>>=' and 'do' notation ==<br />
<br />
All beginners (including me :)) start by thinking that 'do' is some<br />
magic statement that executes IO actions. That's wrong - 'do' is just<br />
syntactic sugar that simplifies the writing of procedures that use IO. 'do' notation eventually gets translated to statements passing "world" values around like we've manually written above and is used to simplify the gluing of several<br />
IO actions together. You don't need to use 'do' for just one statement:<br />
<br />
<haskell><br />
main = do putStr "Hello!"<br />
</haskell><br />
<br />
is desugared to:<br />
<br />
<haskell><br />
main = putStr "Hello!"<br />
</haskell><br />
<br />
But nevertheless it's considered Good Style to use 'do' even for one statement<br />
because it simplifies adding new statements in the future.<br />
<br />
<br />
Let's examine how to desugar a 'do' with multiple statements in the<br />
following example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
putStr "How old are you?"<br />
putStr "Nice day!"<br />
</haskell><br />
<br />
The 'do' statement here just joins several IO actions that should be<br />
performed sequentially. It's translated to sequential applications<br />
of the so-called "binding operator", namely '>>':<br />
<br />
<haskell><br />
main = (putStr "What is your name?")<br />
>> ( (putStr "How old are you?")<br />
>> (putStr "Nice day!")<br />
)<br />
</haskell><br />
<br />
This binding operator just combines two IO actions, executing them<br />
sequentially by passing the "world" between them:<br />
<br />
<haskell><br />
(>>) :: IO a -> IO b -> IO b<br />
(action1 >> action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
If defining operators this way looks strange to you, read this<br />
definition as follows:<br />
<br />
<haskell><br />
action1 >> action2 = action<br />
where<br />
action world0 = let (a, world1) = action1 world0<br />
(b, world2) = action2 world1<br />
in (b, world2)<br />
</haskell><br />
<br />
Now you can substitute the definition of '>>' at the places of its usage<br />
and check that program constructed by the 'do' desugaring is actually the<br />
same as we could write by manually manipulating "world" values.<br />
<br />
<br />
A more complex example involves the binding of variables using "<-":<br />
<br />
<haskell><br />
main = do a <- readLn<br />
print a<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = readLn<br />
>>= (\a -> print a)<br />
</haskell><br />
<br />
As you should remember, the '>>' binding operator silently ignores<br />
the value of its first action and returns as an overall result just<br />
the result of its second action. On the other hand, '>>=' allows us to use the value of its first action - it's passed as an additional parameter to the second one! Look at the definition:<br />
<br />
<haskell><br />
(>>=) :: IO a -> (a->IO b) -> IO b<br />
(action1 >>= action2) world0 =<br />
let (a, world1) = action1 world0<br />
(b, world2) = action2 a world1<br />
in (b, world2)<br />
</haskell><br />
<br />
First, what does the type of the second "action", namely "a->IO b", mean? By<br />
substituting the "IO" definition, we get "a -> RealWorld -> (b, RealWorld)".<br />
This means that second action actually has two parameters<br />
- the type 'a' actually used inside it, and the value of type RealWorld used for sequencing of IO actions. That's always the case - any IO procedure has one<br />
more parameter compared to what you see in its type signature. This<br />
parameter is hidden inside the definition of the type alias "IO".<br />
<br />
Second, you can use these '>>' and '>>=' operations to simplify your<br />
program. For example, in the code above we don't need to introduce the<br />
variable, because the result of 'readLn' can be send directly to 'print':<br />
<br />
<haskell><br />
main = readLn >>= print<br />
</haskell><br />
<br />
<br />
And third - as you see, the notation:<br />
<br />
<haskell><br />
do x <- action1<br />
action2<br />
</haskell><br />
<br />
where 'action1' has type "IO a" and 'action2' has type "IO b",<br />
translates into:<br />
<br />
<haskell><br />
action1 >>= (\x -> action2)<br />
</haskell><br />
<br />
where the second argument of '>>=' has the type "a->IO b". It's the way<br />
the "<-" binding is processed - it just becomes a parameter of<br />
subsequent operations represented as one large IO action. Look at the<br />
next example: <br />
<br />
<haskell><br />
main = do putStr "What is your name?"<br />
a <- readLn<br />
putStr "How old are you?"<br />
b <- readLn<br />
print (a,b)<br />
</haskell><br />
<br />
This code is desugared into:<br />
<br />
<haskell><br />
main = putStr "What is your name?"<br />
>> readLn<br />
>>= \a -> putStr "How old are you?"<br />
>> readLn<br />
>>= \b -> print (a,b)<br />
</haskell><br />
<br />
I omitted parentheses here; both '>>' and '>>=' operations are<br />
left-associative, which means that the 'a' and 'b' bindings introduced<br />
here are valid for all remaining actions. As an exercise, add the<br />
parentheses yourself and translate this procedure into the low-level<br />
code that explicitly passes "world" values. I think it should be enough to help you finally realize how the 'do' translation and binding operators work.<br />
<br />
<br />
Oh, no! I forgot the third monadic operator - 'return'. It just<br />
combines its two parameters - the value passed and "world":<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return a world0 = (a, world0)<br />
</haskell><br />
<br />
How about translating a simple example of 'return' usage? Say,<br />
<br />
<haskell><br />
main = do a <- readLn<br />
return (a*2)<br />
</haskell><br />
<br />
<br />
Programmers with an imperative languages background often think that<br />
'return' in Haskell, as in other languages, immediately returns from<br />
the IO procedure. As you can see in its definition (and even just from its<br />
type!), such an assumption is totally wrong. The only purpose of using<br />
'return' is to "lift" some value (of type 'a') into the result of<br />
a whole action (of type "IO a") and therefore it should generally be used only as the last executed statement of some IO sequence. For example try to<br />
translate the following procedure into the corresponding low-level code:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
when (a>=0) $ do<br />
return ()<br />
print "a is negative"<br />
</haskell><br />
<br />
and you will realize that the 'print' statement is executed anyway. If you<br />
need to escape from the middle of an IO procedure, you can use the 'if'<br />
statement:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0)<br />
then return ()<br />
else print "a is negative"<br />
</haskell><br />
<br />
Moreover, Haskell layout rules allow us to use the following layout:<br />
<br />
<haskell><br />
main = do a <- readLn<br />
if (a>=0) then return ()<br />
else do<br />
print "a is negative"<br />
...<br />
</haskell><br />
<br />
that may be useful for escaping from the middle of a longish 'do' statement.<br />
<br />
<br />
Last exercise: implement a function 'liftM' that lifts operations on<br />
plain values to the operations on monadic ones. Its type signature:<br />
<br />
<haskell><br />
liftM :: (a->b) -> (IO a -> IO b)<br />
</haskell><br />
<br />
If it's too hard for you, start with the following high-level<br />
definition and rewrite it in low-level fashion:<br />
<br />
<haskell><br />
liftM f action = do x <- action<br />
return (f x)<br />
</haskell><br />
<br />
<br />
<br />
== Mutable data (references, arrays, hash tables...) ==<br />
<br />
As you should know, all names in Haskell are bound to one fixed value.<br />
This greatly simplifies understanding of algorithms and optimization of<br />
code, but is inappropriate in some cases. As we all know, there are plenty of<br />
algorithms that are simpler to implement in terms of updatable<br />
variables, arrays and so on. This means that the value associated with<br />
a variable, for example, can be different at different execution points,<br />
so reading its value can't be considered as a pure function. Imagine,<br />
for example, the following code:<br />
<br />
<haskell><br />
main = do let a0 = readVariable varA<br />
_ = writeVariable varA 1<br />
a1 = readVariable varA<br />
print (a0,a1)<br />
</haskell><br />
<br />
Does this look strange? First, the two calls to 'readVariable' look the same, so the compiler can just reuse the value returned by the first call. Second,<br />
the result of the 'writeVariable' call isn't used so the compiler can (and will!) omit this call completely. To finish the picture, these three calls may be rearranged to any order because they appear to be independent of each<br />
other. What is the solution? You already know this - use IO actions! IO<br />
actions guarantee us that:<br />
<br />
# execution order will be retained<br />
# each action will have to be executed<br