Interactive Haskell programs, a primer

These are lecture notes from my Computer Science course. For learning about functional programming, in particular Haskell, I recommend Programming in Haskell.

Functions

There are 3 important functions when dealing with interactive Haskell programs:

interact

interact takes a function of type String -> String, and the entire input from stdin is passed to this function as its input, and the resulting string is output on stdout. Because of the nature of Haskell, the output will seem interactive as it gets evaluated bit by bit; but the function provided is written as if the whole input is specified at once. Remember to think of functional programming as not having a concept of time.

unlines

unlines takes a list, and returns it interleaved with newlines, such as:

Input: unlines ["aa","bb","cc","dd","ee"]
Output: "aa\nbb\ncc\ndd\nee\n"

lines

lines is the reverse of unlines, essentially:

Input: lines "aa\nbb\nbb"
Output: ["aa","bb","bb"]

Writing interactive programs

Generally, interactive programs seem to be of the form:

some_fun :: Show argument => [argument] -> String -> String
some_fun xs = unlines . map doSomething . lines

Though there are more complicated variations (the 2009 paper uses a mapState function which is a state machine).

Why does this work?

Haskell uses ‘Lazy Evaluation’ which is a strategy for program reduction. It works by not evaluating arguments to functions until they are needed, and even then only evaluating as much as is needed by the function. This is why infinite data structures can be used in Haskell. The following would be impossible with strict evaluation…

numbers = numsFrom 0
	where
	numsFrom n = n : numsFrom (n+1)
head numbers

…because the programming language would try to evaluate the entire numbers list (which is infinite) just to return the first element. In Haskell, due to lazy evaluation, this will work.

An interactive program can therefore be formulated as a lazily evaluated function from a list of the user’s inputs to a list of program’s outputs. The computation of the program’s output list always proceeds as far as possible when evaluating the user’s input list, suspending reduction only when the next item in the list is strictly needed.

This entry was posted in fun, lecture. Bookmark the permalink.