Small Factorials Solution in Haskell
Let’s try to solve the codechef’s small factorials problem in Haskell. The code should be able to take in a list of positive integers and output their factorial values.
The solution which I came up is as follows:
-- 'Main' module module Main where -- 'factorial' function definition factorial 0 = 1 factorial n = n * factorial (n - 1) -- 'printAll' function type definition printAll :: [Integer] -> IO () -- 'printAll' function definition printAll [] = return () printAll (x:xs) = do print x printAll xs -- 'convertToFactorial' function type definition convertToFactorial :: Integer -> IO [Integer] -- 'convertToFactorial' function definition convertToFactorial num = do if num == 0 then return [] else do input <- readLn nextRun <- convertToFactorial (num-1) return $ factorial input : nextRun -- 'main' function definition main = do n <- readLn factorials <- convertToFactorial n printAll factorials
If you are coming from a Java/C/.Net background, understanding this code might be little difficult. I will try to explain the code as simple as possible. Any statement that starts with ‘–‘ in a line is considered as comments in Haskell. Note that Haskell is white space sensitive language, which means it uses indentations to identify blocks instead of curly braces (‘{‘ and ‘}’) in Java/C.
The above code has following:
- ‘Main’ module
- ‘factorial’ function definition
- ‘printAll’ function type definition
- ‘printAll’ function definition
- ‘convertToFactorial’ function type definition
- ‘convertToFactorial’ function definition
- ‘main’ function definition
‘Main’ module : Modules in haskell is similar to packages in Java and namespaces in C/C++. Here we have created a namespace with name Main in the first line.
‘factorial’ function definition : The next two statements in the program defines the function ‘factorial’. It is using the recursive call method. It’s like grammar definitions in lexical analyzers. The first statement says if the function is called with 0 as it’s argument, then return 1. The next statement multiplies the input ‘n’ to the output of the recursive call which passes n-1 a argument to the factorial function.
‘printAll’ function type definition : This statement simply declares that type of the function ‘printAll’ as [Integer] -> IO(). This means that the function takes a list of integers as argument and performs an IO operation without returning anything useful (void).
‘printAll’ function definition : These statements define what the function does. The first statement means that if an empty list is passed, then return void. The next statement takes the top element of the list (‘x’) and prints it on to the console and recursively calls the function passing the remaining list of elements (‘xs’).
‘convertToFactorial’ function type definition : This statement simply declares that type of the function ‘convertToFactorial’ as [Integer] -> IO [Integer]. This means that the function takes a list of integers as argument and performs an IO operation and returns a list of integers.
‘convertToFactorial’ function definition : This function is given the total number of elements (num) for which the factorial value has to be found. If num is 0 then it returns an empty list. If num is not 0 then takes in an ‘input’ from IO and recursively calls passing num -1 to get the next n-1 elements and return their factorials as a list which is assigned to ‘nextRun’. Finally, the factorial of the ‘input’ is calculated and appends it as the top element to the other factorial values returned (‘nextRun’), and this value is returned to the caller function.
‘main’ function definition : This is the main function that first takes the total number of elements (‘n’) of which the factorial values needs to be found. It then passes as argument to ‘convertToFactorial’ function which would read ‘n’ inputs and returns their factorials as a list. The list is then passed to the ‘printAll’ function which would print all the elements to the console.