Functional Programming in Haskell
Haskell is considered to be a purely functional programming language. Is there a significant difference between imperative and functional languages? Well, In imperative programming, we get things done by giving a computer a sequence of tasks which it executes. During execution, the computer can change the state. For example, we can set the variable a to 5, then do something and later set it to another value. This shows that in imperative programming we have control flow structures for performing some actions several times.
On the other hand, in pure functional programming, we do not tell the computer what to do. As such. Instead, you tell it what the stuff is and what it means? For example, the factorial of a number is the product of all numbers from 1 to that number, the sum of numbers in a list is the first number plus all the other numbers in the list, etc. These instructions are usually expressed in the form of functions. Also, we cannot set a variable to something and later change it to something else in functional programming. For example, if we set the value of variable a to 5, we cannot later change it to something else because we just said it was 5.
Although this at first may seem to be a limiting factor, but nevertheless, functional programming has some nice benefits. A function will only calculate something and return it as a result. If we call a function twice with the same parameters, we are guaranteed it will return the same result. This is known as referential transparency. It allows the compiler to reason about the program’s behavior. Also, the programmer can deduce and even prove that a function is correct. This means that the programmer can build complex functions by gluing the simple ones together.
Functional programming languages like Haskell are lazy. It will only execute functions and calculate things when you force it to show a result. This allows us to think of a program as a series of transformations on data. Functional programming supports infinite data structures. For example:
Suppose we have an immutable list of numbers X = [ 2, 4, 5, 7, 8, 9] and a function doubleMe which multiplies every element in the array by 2 and returns a new list. In Haskell, calling the function doubleMe without forcing it to show you the result will end in the program terminating without any output. This is why it is called a lazy language
Introduction to functional programming in Haskell
First, you should install your favorite text editor and a Haskell compiler. If you are not new to this language then you probably have one installed. However, if you do not have one in mind then our experts recommend GHC which is a widely used Haskell compiler.
The GHC compiler takes a Haskell script, which usually has a .hs extension. And compiles it. This compiler also has an interactive mode that allows you to interact with scripts. Furthermore, it allows the calling of functions from scripts that you load. The results will be displayed immediately. You can invoke the interactive mode by typing ghci on your prompt.
Features of functional programming languages like Haskell
- Higher-order functions (HOFs)
These are functions that take other functions as their arguments. An excellent example of HOF is map. It takes a list and a function as its arguments, applies the function to all the elements in the list and returns the list of results. Higher-order functions are vital because they can be used to refactor code and reduce the amount of repetition. In Haskell, we can use maps or folds to express most for loops.
In addition to return values, functional programming allows expressions to yield actions (side effects). These actions emphasize the importance of return value as an outcome of a function. Functional programming languages that exhibit this feature are called pure. Writing a significant part of a functional program in a pure fashion is usually beneficial. This is because impure codes are more susceptible to errors.
- Immutable data
Functional programming is based on immutable data. Existing values are not altered. Instead, the original is preserved and altered copies are created. We cannot modify the unchanged parts of a structure. As a result, they are often shared between new and old copies to save memory.
Recursion is canonical and is heavily used in functional programming. It offers the only way to iterate. Implementations in functional programming usually include tall call optimization. This ensures that excessive memory is not consumed by heavy recursion.