Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding pure functions in Haskell with IO

Tags:

haskell

Given a Haskell value (edit per Rein Heinrich's comment) f:

f :: IO Int
f = ... -- ignoring its implementation

Quoting "Type-Driven Development with Idris,"

The key property of a pure function is that the same inputs always produce the same result. This property is known as referential transparency

Is f, and, namely all IO ... functions in Haskell, pure? It seems to me that they are not since, lookInDatabase :: IO DBThing, won't always return the same value since:

  • at t=0, the DB might be down
  • at t=1, the DB might be up and return MyDbThing would result

In short, is f (and IO ... functions in general) pure? If yes, then please correct my incorrect understanding given my attempt to disprove the functional purity of f with my t=... examples.

like image 755
Kevin Meredith Avatar asked Dec 15 '15 03:12

Kevin Meredith


People also ask

How is Haskell IO pure?

Haskell is a pure language Being pure means that the result of any function call is fully determined by its arguments. Procedural entities like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell.

What does pure function do in Haskell?

A function is called pure if it corresponds to a function in the mathematical sense: it associates each possible input value with an output value, and does nothing else.

What is IO () Haskell?

IO is the way how Haskell differentiates between code that is referentially transparent and code that is not. IO a is the type of an IO action that returns an a . You can think of an IO action as a piece of code with some effect on the real world that waits to get executed.

Is IO impure Haskell?

In spite of Haskell being purely functional, IO actions can be said to be impure because their impacts on the outside world are side effects (as opposed to the regular effects that are entirely contained within Haskell).


1 Answers

IO is really a separate language, conceptually. It's the language of the Haskell RTS (runtime system). It's implemented in Haskell as a (relatively simple) embedded DSL whose "scripts" have the type IO a.

So Haskell functions that return values of type IO a, are actually not the functions that are being executed at runtime — what gets executed is the IO a value itself. So these functions actually are pure but their return values represent non-pure computations.

From a language design point of view, IO is a really elegant hack to keep the non-pure ugliness completely isolated away while at the same integrating it tightly into its pure surroundings, without resorting to special casing. In other words, the design does not solve the problems caused by impure IO but it does a great job of at least not affecting the pure parts of your code.


The next step would be to look into FRP — with FRP you can make the layer that contains IO even thinner and move even more of non-pure logic into pure logic.

You might also want to read John Backus' writings on the topic of Function Programming, the limitations of the Von Neumann architecture etc. Conal Elliott is also a name to google if you're interested in the relationship between purity and IO.


P.S. also worth noting is that while IO is heavily reliant on monads to work around an aspect of lazy evaluation, and because monads are a very nice way of structuring embedded DSLs (of which IO is just a single example), monads are much more general than IO, so try not to think about IO and monads in the same context too much — they are two separate things and both could exist without the other.

like image 176
Erik Kaplun Avatar answered Oct 21 '22 03:10

Erik Kaplun