Haskell Language IO Getting the 'a' "out of" 'IO a'


A common question is "I have a value of IO a, but I want to do something to that a value: how do I get access to it?" How can one operate on data that comes from the outside world (for example, incrementing a number typed by the user)?

The point is that if you use a pure function on data obtained impurely, then the result is still impure. It depends on what the user did! A value of type IO a stands for a "side-effecting computation resulting in a value of type a" which can only be run by (a) composing it into main and (b) compiling and executing your program. For that reason, there is no way within pure Haskell world to "get the a out".

Instead, we want to build a new computation, a new IO value, which makes use of the a value at runtime. This is another way of composing IO values and so again we can use do-notation:

-- assuming
myComputation :: IO Int

getMessage :: Int -> String
getMessage int = "My computation resulted in: " ++ show int
newComputation :: IO ()
newComputation = do
  int <- myComputation       -- we "bind" the result of myComputation to a name, 'int'
  putStrLn $ getMessage int   -- 'int' holds a value of type Int

Here we're using a pure function (getMessage) to turn an Int into a String, but we're using do notation to make it be applied to the result of an IO computation myComputation when (after) that computation runs. The result is a bigger IO computation, newComputation. This technique of using pure functions in an impure context is called lifting.