Following the system of lambda calculus, as defined by Alonzo Church and later refined, Haskell attempts to work as a function-based programming langauge, rather than a sequentially-ordered one. Because of this attempt to increase functionality (speaking of functions, not performance) of the language, definitions are split into two groups.
- Pure functions do not change a state, depend on a temporal variable, or deal with user input/output.
- Impure functions include one of those things mentioned above.
Consider two functions, f and g, as defined
f x = 5 * x
g = do
putStrLn "How are you?"
In this case, f would be considered a pure function. All it does is provide a value that is five times its input. Therefor, it does not change a state or do anything requiring outside input.
g, however, would be considered an impure function. It prints two statements to the standard output, thereby providing a value to the user, rather than returning a value useable by other functions.
Haskell works better when pure functions are used as often as possible. This is because function composition can be used effectively in Haskell. This is almost exactly like function composition in basic algebra. For example:
f x = 5 * x
h o = o . o
In the above example, both f and g are pure haskell functions. f takes a parameter x and returns a value that is five times that input. g takes a function o and composes it onto itself. If these functions were used at some point such as below,
(h f) 5
The return value would be 125. First, f is passed as a parameter to h, which returns a function that can be understood as meaning (5 * (5 * x)). Then, the value of 5 is passed to this result and x assumes that value, creating a multiplication of 5.
Haskell implements some control operators, which help functions decide what to do.
The equivalent of an if statement in Haskell is implemented by guards, which look like the following:
f x =
| x == 0 = 1
| otherwise = x * f (x – 1)
The above shows not only the use of guards, but also a recursive statement. Almost all functions that are useful in Haskell and other functional programming languages are recursive to an extent.
To help with all the recursive functions, list comprehension is optimized. The below gives an example of a list containing all the even numbers and a list containing all the multiples of 3 and 5:
e = [2, 4..]
t = [x | x <- [1..], x `mod` 3 == 0 || x `mod` 5 == 0]