An installer for GHC can be downloaded from its home page or as part of the Haskell Platform. For reference, the full documentation is available that can be searched through Hoogle.

In this lab session, we are going to implement the TextIO monad that emulates some of the console operations, such as reading and writing to a virtual console (represented as a set of buffers) without the IO monad.

Emulating Textual Input/Output Monadically

The TextIO is the following type:

TextIO :: * -> *

For the definition, we are going to employ the following helper types:

type Input  = String
type Output = String

where Input stores the characters for the standard input, and Output stores the characters for the standard output. The operations of TextIO shall always read the characters they need from a value of type Input, and they shall always return their result in an n-tuple that consists of the following:

Hence the TextIO monad works as follows. Consider the following action:

exampleTIO = do
  write "Hi "
  s <- readLine
  writeLn (s ++ "!")
  return 42

This could be then run with the runTextIO function:

runTextIO :: TextIO a -> Input -> (a, Input, Output)

that then gives the following result:

TextIO*> runTextIO exampleTIO "Mikey\nFreddy\n"
(42,"Freddy\n","Hi Mikey!\n")

The Implementation

Define a type class instance for the Functor, Applicative, and Monad classes, together with the following monad-specific operations.

Printing a string:

write :: String -> TextIO ()

Printing a string with line break. Note that it could be expressed with the help of write.

writeLn :: String -> TextIO ()

Reading a single character from the input.

readChar :: TextIO Char

Reading a string until line break. Note that it could be even expressed with the help of readChar.

readLine :: TextIO String

Further Goals

Once the implementation is complete, consider the following refactoring steps:

Enjoy the fun! :-)