A pure function in Haskell is a function that always produces the same output for the same input and has no side effects. In other words, it does not change any state or perform any input/output (I/O) operations, and it does not depend on any external mutable state or hidden variables.
Pure functions have some important properties:
1. Referential transparency: The function can always be replaced by its value without changing the behavior of the program, which makes reasoning about code easier.
2. Lack of side effects: Pure functions do not interact with the outside world or change any global state, which means they are easier to test, debug, and maintain.
An example of a pure function in Haskell is the addition function:
add :: Int -> Int -> Int
add x y = x + y
Here’s how the function definition would look like in LaTeX:
add : ℤ × ℤ → ℤ
Given the same input values for ‘x‘ and ‘y‘, this function will always return the same result, and it does not have any side effects or depend on any external state. In contrast, an impure function might depend on mutable state, perform I/O operations or throw exceptions.
Here’s a simple example in Haskell of an impure function:
import System.Random
randomInt :: Int -> IO Int
randomInt n = randomRIO (1, n)
The ‘randomInt‘ function takes an integer ‘n‘ and returns a random integer between 1 and ‘n‘ using the ‘IO‘ monad to encapsulate impure actions. Since the output depends on a random number generator, the function is not referentially transparent and is considered impure.
In summary, pure functions in Haskell are those which produce the same results given the same input arguments without any side effects, and their properties facilitate easier reasoning, testing, and maintenance of the code.