Introduction to Haskell IO
Jump to navigation
Jump to search
This article is a draft, with further revisions planned by User:Newsham. Draft is typically different than stub in that the User:Newsham is normally in an active edit process. Feel free to help by expanding the article..
About this document
XXX. The target audience is a beginning haskell programmer who has some haskell under his belt but is not yet comfortable with IO or monads. The goal is to get the reader proficient in writing useful code as quickly as possible. The pace will be slow and detailed to avoid confusing programmers who are unfamiliar with haskell, may not have a strong background in math or functional programming.
Sections
- Introduction to Haskell IO/General introduction
- Actions
- Introduction to Haskell IO/Introduction to IO
- Introduction to Haskell IO/Monadic lifters and IO
- Introduction to Haskell IO/Introduction to more IO
Notes
XXX Here is the planned layout - needs to be broken into the above articles
- intro
- programming in haskell is not hard!
- even the scary "monad" stuff.
- explain target and goals
- what you should already know
- partial application, types, constructed types, general haskell stuff..
- what you should already know
- we'll get you writing code as soon as possible!
- describe chapters
- skipping around is allowed. the "do" and "IO" lessons have some important concepts that are used throughout. the rest can be read as needed.
- programming in haskell is not hard!
- talk about do notation and actions
- introduce "actions"
- actions are inert until executed
- actions can be combined into larger actions
- actions can return a value or nothing.
- we can pretend that actions take parameters (although they dont). this is done by making a function which returns an action THERES A DIFFERENCE BETWEEN AN ACTION AND A FUNCTION THAT MAKES AN ACTION!
- action types are monads. there are different types, such as "IO" actions. dont worry about that yet!
- introduce "do" as a way to combine actions together
- do-binding similar to let-binding, but with an action
- show two-action do.
- adjacent actions get combined - nesting similar to let-nesting
- different rules for combining...
- show nested two-action do's
- let-binding allowed
- "return" is an action that returns its input (like identity). x <- return 5 for example It DOES NOT "return" control flow out of the current action or do block!
- the entire do-block is one action.
- you can still use things like "if" as long as they evaluate to an action.
- if you need multiple actions in a "then" you need a "do" block to combine them down to one action!
- we'll see example later to clarify (hope your brain didnt hurt on that)
- nested do's
- do's as separate functions.
- introduce "actions"
- the most important type of actions are IO actions
- introducing "IO"
- meaning
- how it gets invoked
- IO actions are inert until "run by main"
- combining rule
- rule for combining actions: one happens, then the next happens. the results of the first are observable to the second (and successive). IO actions are performed sequentially.
- what "return" means
- Some simple IO functions (file, cmd)
- IO action examples -
- printing
- reading line
- opening file
- reading file
- make sure to show if/then/else with nested do block!
- show some recursion.
- examples
- read a line, write a line
- read a line, increment the value, write that
- read two lines, add the value, write that
- adding random numbers to user input
- an important note about IO monads
- you cannot escape! there's a reason for this
- unless you cheat: unsafePerformIO
- introducing "IO"
- using the "M"s
- lifts
- what liftM means in IO
- liftM is just short for do { x <- act1; return (f x) }
- rewrite example of read one line add the vale and write that
- what liftM2 means in IO
- liftM2 is just short for do { x <- act1; y <- act2; return (x `op` y) }
- rewrite example of read two lines add the value and write that
- this generalizes - liftM3, liftM4, ...
- what liftM means in IO
- what fmap means in IO
- some control flow in IO
- when, unless
- replicateM_, replicateM
- forM_, forM
- mapM_, mapM are just swapped around forM_, forM
- loop carried variables: foldM_ and foldM
- rewrite previous recursion example using one of these.
- show several other examples
- exceptions?
- there's more...
- fixIO?
- lifts
- More IO functions for you
- you already know enough to write some complex real-world programs!
- throw in a complex example.. open a network socket, connect to a service, interact with it, print a result, and shut down.
- which functions?
- errors
- ioError, userError, catch
- command
- getArgs, getProgname, getEnv
- exitFailure
- file and console io
- putChar, putStr, putStrLn, print
- getChar, getLine, getContents, isEOF
- readFile, writeFile
- readIO, readLn
- openFile :: FilePath -> IOMode -> IO Handle
- openBinaryFile
- stdin/stdout/stderr
- hClose hGetChar hReady
- hGetLine hPutChar hPutStr hPutStrLn hPrint, hIsEOF
- interact
- filesystem
- createDirectory, removeDirectory, renameDirectory
- setCurrentDirectory
- getDirectoryContents, doesFileExist, doesDirectoryExist
- random
- randomIO, randomRIO
- time? (these are somewhat complicated)
- getClockTime, toCalendarTime, formatCalendarTime
- system
- network
- listenOn, accept, connectTo, sClose, sendTo, recvFrom
- getHostByName, getHostByAddr,
- signals
- errors
- Some advanced IO stuff (move to later chapter? appendix?)
- teaser? light mention?
- IORefs? ST?
- IO with packed strings?
- newUnique?
- threads? STM?
- FFI?
- System.Win32?
- Graphics?
- you already know enough to write some complex real-world programs!
- "global" variables, the Reader and State monads.
- these actions dont run themselves. you have to run them.
- describe running later in an example
- reader lets you have read-only state that gets passed around implicitely
- rule for combining reader actions
- just ordering?
- return just "wraps" the value, as always.
- reader has function "ask"
- small functional example
- show how to "run" an action.
- small IO example
- the ReaderT monad. We can combine reader with other action types.
- running this one is more complicated.. we need both the reader and the IO to run.
- liftIO is needed. what does it do?
- we can use all the "M" tricks we learned from IO
- what liftM, liftM2, etc.. mean for reader
- slightly bigger example
- more complex data.
- reader also has "asks" that can be used to extract complex state or process it.
- if we want to write to the global state, we need the State monad.
- state's rules for combining
- successive (enclosed) actions run with access to the changes of the previous action. Exactly as we would expect.
- new functions "get", "put", "gets", "puts". No "ask" or "asks".
- state needs to be run (just like reader did)
- we can use all the "M" tricks we learned from IO
- a moderate example building on the reader example
- use StateT
- there's also "Writer". Its like State - Reader.
- it has "tell". You figure it out!
- these actions dont run themselves. you have to run them.
- Maybe - computation with simple failure. search.
- very different meaning than other actions!
- rule for combining
- next action only runs if current one didnt "fail" (return Nothing)
- what "return" does
- hey, this "action" isn't inert!
- Maybe is used often in the libraries
- list lookup
- map lookup
- some maybe functions
- fromJust, isJust, ...
- the "M" bunch
- liftMs work... what they mean
- conditionals and looping?
- a new one: mplus
- implementing a search algorithm using Maybe
- (some example using monad transformers?)
- Error - errors with failure values.
- List
- computation that can return many or no values.
- generators
- search algorithms again!
- rule for combining actions
- next actionruns with ALL VALUES from the current action
- or doesn't run if the list is empty!
- what "return" does
- some simple generators
- relate generators to list comprehensions
- introduce guard and relate that to list comprehensions
- what the normal "M" guys mean for lists
- List is a superset of Maybe in many ways
- how mplus works
- our Maybe search code previously works with no code modifications!
- instead of finding the FIRST result, it finds ALL results!
- as usual we can combine list monads with other monads
- how about an search algorithm using StateT?
- the ((->) r) monad
- actions are functions. These are of course inert.
- rule for combining combines functions
- we can use "do" notation to combine some functions in complex ways!
- we can use the normal "M" tools too!
- liftM
- mapM
- join
- What it all means
- the common theme here was
- some action
- actions can be combined. there's a rule for combining
- there's a way to make an action that returns a value
- the monad laws
- thats all a monad is.
- do, liftM, etc.. work with any monad.
- review the definition? show the definition of some more of them?
- do notation is just a convenience
- it translates into something very similar to let-binding.
- you can rewrite do blocks as nested do blocks where each do block combines only two actions. This is how actions are combined... its called "bind" (we're doing do-binding!)
- the "bind" operator is called ">>="
- show example of desugaring.
- work through the entire example showing how it gets worked out (perhaps Maybe monad would be good here)
- you can use bind directly! Sometimes the code is simpler. Sometimes its not. Show some examples.
- do has some other "goodies" like pattern matching and "lets" lets desugar to the obvious thing.
- what about IO!@? IO can be thought of as a function on the real world! in reality IO enforces ordering, which lets haskell do its lazy evaluation. It doesnt really represent "the real world" internally some how!
- you can make your own if you want!
- show examples of some of the other implementations
- State
- Maybe
- mplus
- when you do, people can use your new monad in do blocks!
- all of the "M" tools are yours for free! (thats why we use general abstractions! not to confuse you!)
- instance Monad. small example
- show examples of some of the other implementations
- the common theme here was
- Where to go from here
- good tutorial on monad transformers
- the ghc library documentation
- write code!