Recursive definitions of few standard prelude functions

Saturday, Dec 26, 2020
Functional Haskell

One thing I like about functional programming is the ease with which one can re-create built-in functions. Rewriting library functions on your own aids in understanding and reduces the feeling that library functions are any special. In that spirit, let's write few definitions from standard prelude on our own:

and

Decide if all logical values in a list are True:

and :: [Bool] -> Bool
and [] = True
and (x:xs) = x && and xs

First, we write the signature saying that and is a function that maps a Bool list to a single Bool value. If the list is empty, then the result is True, otherwise, it is value of head && applying and recursively to the tail of the list.

concat

Concatenate a list of lists:

concat :: [[a]] -> [a]
concat [] = []
concat ([]:xss) = concat xss
concat ((x:xs):xss) = x : concat (xs:xss)

So, concat is a function that maps list of lists of any type to a single list of such type. It results in an empty list for an empty list. If the head is an empty list, head is thrown out and concat is applied recursively to the tail of the list. Otherwise, each element of sub-list is consed to recursively applying concat to list containing the tail of list that is being processed and rest of the lists.

replicate

Produce a list with n identical elements:

replicate :: Int -> a -> [a]
replicate 0 x = []
replicate n x = x : replicate (n-1) x

replicate takes an integer and another argument of any type and produces a list of such type. For zero replications, it produces an empty list. For positive integers, x is consed to result of recursively applying replicate n-1 times to the input value.

!!

Select nth element of a list:

(!!) :: [a] -> Int -> a
[] !! _ = error "index too large"
(x:xs) !! 0 = x
(x:xs) !! n = xs !! (n-1)

So, !! is a function that maps a list of any type and an integer to a single value of such type. Applying !! to an empty list results in an error. For a non-empty list, $0^{th}$ index results in head of the list. For non-zero index, the function is recursively applied to the tail of the list asking for $(n-1)^{th}$ value.

elem

Decide if a value is an element of a list:

elem :: Eq a => a -> [a] -> Bool
elem _ [] = False
elem e (x:xs) | x == e = True
              | otherwise = elem e xs

elem maps a value of any type that is an instance of Eq class and a list of such values to a single Bool value. Probing for any value in a empty list results in False. Otherwise, if the head matches the value then the result is True and if not, elem is recursively applied to the tail of the list.