Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Haskell really a purely functional language considering unsafePerformIO?

Haskell is generally referenced as an example of a purely functional language. How can this be justified given the existence of System.IO.Unsafe.unsafePerformIO ?

Edit: I thought with "purely functional" it was meant that it is impossible to introduce impure code into the functional part of the program.

like image 282
Stefan Schmidt Avatar asked Jun 26 '10 16:06

Stefan Schmidt


People also ask

Is Haskell a purely functional language?

Haskell features lazy evaluation, lambda expressions, pattern matching, list comprehension, type classes and type polymorphism. It is a purely functional language, which means that functions generally have no side effects.

Is everything a function in Haskell?

> In fact, in haskell, everything is a function.

How is Haskell pure?

A function is pure when given the same input, you always get the same output. It is as simple as that! No matter how many times we call numberOfItems , if we give it the same ShoppingCart we'll always get the same quantity back.


2 Answers

The Languages We Call Haskell

unsafePerformIO is part of the Foreign Function Interface specification, not core Haskell 98 specification. It can be used to do local side effects that don't escape some scope, in order to expose a purely functional interface. That is, we use it to hide effects when the type checker can't do it for us (unlike the ST monad, which hides effects with a static guarantee).

To illustrate precisely the multiple languages that we call "Haskell", consider the image below. Each ring corresponds to a specific set of computational features, ordered by safety, and with area correlating to expressive power (i.e. the number of programs you can write if you have that feature).

The language known as Haskell 98 is specified right down in the middle, admitting total and partial functions. Agda (or Epigram), where only total functions are allowed, is even less expressive, but "more pure" and more safe. While Haskell as we use it today includes everything out to the FFI, where unsafePerformIO lives. That is, you can write anything in modern Haskell, though if you use things from the outer rings, it will be harder to establish safety and security guarantees made simple by the inner rings.

alt text

So, Haskell programs are not typically built from 100% referentially transparent code, however, it is the only moderately common language that is pure by default.

like image 95
Don Stewart Avatar answered Sep 20 '22 21:09

Don Stewart


I thought with "purely functional" it was meant that it is impossible to introduce impure code...

The real answer is that unsafePerformIO is not part of Haskell, any more than say, the garbage collector or run-time system are part of Haskell. unsafePerformIO is there in the system so that the people who build the system can create a pure functional abstraction over very effectful hardware. All real languages have loopholes that make it possible for system builders to get things done in ways that are more effective than dropping down to C code or assembly code.

As to the broader picture of how side effects and I/O fit into Haskell via the IO monad, I think the easiest way to think of Haskell is that it is a pure language that describes effectful computations. When the computation described is main, the run-time system carries out those effects faithfully.

unsafePerformIO is a way to get effects in an unsafe manner; where "unsafe" means "safety must be guaranteed by the programmer"—nothing is checked by the compiler. If you are a savvy programmer and are willing to meet heavy proof obligations, you can use unsafePerformIO. But at that point you are not programming in Haskell any more; you are programming in an unsafe language that looks a lot like Haskell.

like image 27
Norman Ramsey Avatar answered Sep 23 '22 21:09

Norman Ramsey