Compiled Chronicles

A software development blog by Angelo Villegas

Functional Programming

Late part of the year 2015, TU Delft released a MOOC about Functional Programming on edX.org using Haskell. If you already know Swift, then you know that it is a multi-paradigm language that includes functional programming as one of it’s paradigm; and because of this, it piqued my interest to enroll in this course.

What is Functional Programming?

Functional programming is a programming paradigm that treats computation as the evaluations of mathematical functions and avoids changing state and mutable data. It is a style of programming that models computations as the evaluations of expressions.

In functional programming, you will handle immutable states most (if not all) of the time as it typically avoids mutable states. It is a good thing to remember that functions, not objects, are used as the fundamental building blocks of a functional program.

A Short History Lesson

  • Functional programming has its roots in lambda calculus developed by Alonzo Church back in the 1930s. Lambda calculus (λ-calculus) is a formal system for expressing computations based on function abstraction and application using variable binding and substitution.
  • John McCarthy then develops Lisp, the first functional language, with influences from the lambda calculus, originally created as a practical mathematical notation for computer programs.
  • In the 1960s, Peter Landin develops ISWIM, the very first pure functional language that is based strongly on the lambda calculus. Although not implemented, it has proved very influential in the development of functional programming languages.
  • In the 70s, John Backus develops FP, a functional programming language to support higher-order functions. If the name sounds familiar, then you probably read about him from another site or a book as he designed Fortran (previously FORTRAN).
  • Came the 80s, the decade when an international committee of researchers initiates the development of Haskell, a standardised, general-purpose, purely functional, programming language. It is named after Haskell Curry, an American mathematician and logician.

Core Concepts

A number of concepts are specific to functional programming. However, programming languages are often hybrids of several paradigms that other programmers using other paradigms may have utilised some of these concepts.

Higher-order functions

Higher-order functions are functions that can either take other functions as arguments or return functions as a result.

An example of this is the higher-order function twice that accepts a function and a list of numbers:

twice :: Num a => ([a] -> a) -> [a] -> a
twice f xs = f xs + f xs

main :: IO ()
main = print $ twice sum [1..5] -- 30
let twice f xs = f xs + f xs

twice Array.sum [| 1..5 |]
|> printf "%A" // 30

Pure functions

For a function to be considered pure, the function must always evaluate the same result given the same argument values and evaluation of the result does not cause any observable side effects.

What the f… is a side effect?

Side effect, in computer science, is a function or expression that modifies some or all states; for instance, changing the value of a variable can cause a side effect. In medicine, for example, a drug will have a main effect such as reducing pain, and sometimes a side effect of causing sleepiness. The purpose of the drug is not to cause sleepiness but sometimes that happens as an unintended extra result.

For example, the function sq doesn’t have side effects. It’s result depends only on its input argument and no state has been changed, and therefore will always return the same result given the same argument value.

sq :: Int -> Int
sq n = n * n

main :: IO ()
main = print $ sq 5 -- 25
let sq n = n * n
sq 5
|> printf "%A" // 25

Recursion

You know looping, right? Then this is something similar to looping, but instead of expressions, you’re looping a function. Iteration or looping in functional language is accomplished via recursion. Some programming languages support recursion by allowing a function to call itself within the program.

Let’s take this function splitDigits, for example:

splitDigits :: Int -> [Int]
splitDigits 0 = []
splitDigits n = splitDigits (n `div` 10) ++ [n `mod` 10]

main :: IO ()
main = print $ splitDigits 12345 -- [1, 2, 3, 4, 5]
let rec splitDigits n =
    match n with
    | n when n <= 9 -> [n]
    | n -> splitDigits (n/10) @ [n % 10]

splitDigits 12345
|> printf "%A" // [1; 2; 3; 4; 5]

The function’s primary function is to split every digit of a number to a list of numbers. In the example function splitDigits, we gave it the number 12345 and will split the given value to [1, 2, 3, 4, 5].

Currying

Currying is a technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions to allow them to take less argument than before. It was introduced by Gottlob Frege, developed by Moses Schönfinkel, and further developed by Haskell Curry.

f :: a -> b -> c

Is the curried form of

f' :: (a, b) -> c

Let’s try an example using JavaScript, we will write a function called add normally.

function add(a, b) {
  return a + b;
}
add(3, 4); // returns 7
add(3, 2); // returns 5

Every time you will use the add function, you will need to call it, in full, again even if we already know the first argument. We can write this function, however, in a curried form.

function add (a) {
  return function (b) {
    return a + b;
  }
}
var add3 = add(3);
add3(4); // returns 7
add3(2); // returns 5
Why use curried functions?

With curried functions, you get easier reuse of more abstract functions. In shorter form, write code, use it repeatedly. Currying is not practiced by many developers outside Haskell; languages like Haskell though, is mandatory to learn currying because all functions in Haskell are curried by the language itself, so to speak.

Why not Object-Oriented Programming?

When developing software, especially in a service-based company, it’s not always the same software evolution; there’s always a point in time that you will anticipate a different approach.

While both programming paradigm are used in software development, object-oriented programming is based on the concept of objects and add new classes which implement new methods while the existing classes will be, virtually, left alone. Functional Programming, on the other hand, is based on the concept of mathematical functions and add new operations by adding new functions which compute with existing data types, and the existing functions will be, virtually, left alone.

By these concepts, you can choose what programming paradigm best suits your software evolution.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *