Introduction to Functional Programming [Part 1]

Think Functional

Posted by Nivin Anton Alexis Lawrence on September 15, 2018

Recently by the same author:


Introduction to Functional Programming [Part 2]

Think Functional


Nivin Anton Alexis Lawrence

Human

Introduction

The main motive of this post is to make readers get interested in functional programming, learn the critical difference between functional and imperative, provide code snippets to get readers started in writing functional code, and also set up their system to run/compile Haskell. The article is sectioned in to - motivating readers by pointing out on what they are missing by not knowing functional; second, get introduced to Haskell build tool; third, provide primitive code snippets that help them to code basic program in Haskell (e.g., input, output, iterate, conditional, etc.). At last, understanding the core ideas of functional programming and discuss trade-offs.

Motivation

In the current programming era, where multi-processor CPU and storing data have become cheap. The programmers have started to leverage this new computing system by changing the programming paradigm to being purely functional. Also, we are in a place where we are ready to trade off CPU utilization for faster computation. We wanted to process big data in a reasonable amount of time. To utilize the CPU efficiency to the most, we have started to write concurrent programming. Functional programming helps programmers to write clean, fast, and easy to test concurrent programming at ease.

Tools

Stack

Stack is a cross-platform program for developing Haskell projects that allow novice or advanced haskell programmers to:

  1. creating new project with stack - stack new words
  2. compiling stack project - stack ghci
  3. build your project - stack build
  4. initialization the project - stack init
  5. execute - stack exec name-exe

GHC

GHC is the compiler and interpreter for haskell programming.

Hoggle

Hoogle is a Haskell API search engine, which allows you to search many standard Haskell libraries by its function name or signature.

Concepts

Snippet

Before getting into core concepts in functional programming, let’s try to gather primitive code snippets that allow impatient readers started writing small Haskell code. Note, for any programming language; the core sections are input, output, arranging code section (function, control flow), and data segments.

Main

Example 1: create a simple function that prints hello world.

main = putStrLn "Hello World."

Example 2: create a simple function that takes input args.

import System.Environment
import System.Exit

main = getArgs >>= parse >>= putStr . tac
tac = unlines . reverse . lines

parse ["-h"] = usage >> exit
parse ["-v"] = version >> exit
parse [] = getContents
parse fs = concat `fmap` mapM readFile fs

usage = putStrLn "Help Here."
version = putStrLn "Version here."
exit = exitWith ExitSuccess

Input and Output

Example 1: create a function the reads string and outputs.

main = do
  putStrLn "enter your name."
  name <- getLine
  putStrLn $ "Hey " ++ name ++ "!!."

Conditional Statements

Haskell conditional statements is similar to that of any programming languages. The cool thing in Haskell is it also uses conditional statements to decide the control flow of the function sections using guards and pattern matching (we will learn more about it in below section). In case of logic decision made within the function section, we use if, let or case to evaluate expression.

Example 1: Using if condition to decide if a number is even or odd.

isEvenNumber n = 
    if n `mod` 2 == 0
        then True
        else False

Example 2: Using case condition to decide if a number is even or odd.

isEvenNumber n = 
    case n `mod` 2 of
        0 -> True
        1 -> False

Iteration

Iteration in haskell are done either through forM, map or using recursion (just like any other language). Nice thing about haskell is lazy evaluation, it doesn’t evaluate a piece of code until its results are needed for computation.

Example 1: Print number from 1..n using for loop.

loopIt n = forM_ [0 .. n] $ \n -> print n

forM_ signature is :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()

Example 2: Print number from 1..n using map.

loopIto n = mapM_ print [0 .. n]

mapM_ signature is :: Foldable t, Monad m) => (a -> m b) -> t a -> m () If you notice closely the both are same with arguments flipped. We will learn about foldable and monad in later section.

Example 3: Print number from 1..n using recursion.

loopItRecursion :: Int -> IO ()
  loopItRecursion 0 = print 0
  loopItRecursion n = do
    loopItRecursion (n - 1)
    print n

Or

loopItRecursion :: Int -> IO ()
  loopItRecursion 0 = print 0
  loopItRecursion n = loopItRecursion (n - 1) >> print n

Note: Since we wanted to execute sequence of input/output operation, we have introduced do. More about “do” can be found here: link

Data Segment

Algebraic data types: In above section we have used primitive types in haskell. Now lets take a look at user defined types. For illustration, let build a data model for library checkout system. When a user checks out a book we wanted to record his/her (personId, checkoutTime and bookId). In haskell we can define a new data type using value constructors.

data LibraryManagement = CheckOutRecord { personId :: Int
                                        , checkoutTime :: Int
                                        , bookId :: Int
                                        } deriving (show)

Note: Here CheckOutRecord is the value constructor, both the type name and the value constructors have to be capitalized. Value constructor are functions that return a value of data type. So here, if you take a look at the signature of CheckOutRecords:

CheckOutRecord :: Int -> Int -> Int -> LibraryManagement

Awesome right!. There is lot to cover in data segments (record syntax, type parameters, derived instances and type synonyms). Will cover them soon.