Skip this step by step.
The length function obviously has the type you described; in Haskell it Num n => [a] -> n . Equivalent Haskell length function (it uses Int instead of any Num n ).
The swap function takes a function to call and change its first two arguments. You did not receive the signature quite correctly; this is (a -> b -> c) -> b -> a -> c . Equivalent Haskell flip function.
The foldr function is of the type that you described; namely (a -> b -> b) -> b -> [a] -> b . Equivalent Haskell foldr function.
Now let's see what each auxiliary expression in the main expression means.
The expression swap (:) [] takes a function (:) and swaps its arguments. The function (:) is of type a -> [a] -> [a] , so swap ping gives [a] -> a -> [a] ; Thus, the whole expression is of type a -> [a] , because the swapped function is applied to [] . What the resulting function does is that it builds a list of one item specified by that item.
For simplicity, return this part to the function:
singleton :: a -> [a] singleton = swap (:) []
Now the following expression (:) . length . singleton (:) . length . singleton (:) . length . singleton . Function (:) is still of type a -> [a] -> [a] ; what the function (.) does is that it makes up the functions, so if you have a function foo :: a -> ... and a function bar :: b -> a , foo . bar foo . bar will be of type b -> ... Expression (:) . length (:) . length is of type Num n => [a] -> [n] -> [n] (remember that length returns a Num ), and the expression (:) . length . singleton (:) . length . singleton (:) . length . singleton is of type Num => a -> [n] -> [n] . That the resulting expression does this is strange: given any value of type a and some list, it ignores a and adds the number 1 to this list.
For simplicity, we will make a function out of this:
constPrependOne :: Num n => a -> [n] -> [n] constPrependOne = (:) . length . singleton
You should already be familiar with foldr . He performs the right shift above the list using the function. In this situation, it calls constPrependOne for each element, so the expression foldr constPrependOne [] simply creates a list of them with an equal length in the input list. So make a function out of this:
listOfOnesWithSameLength :: Num n => [a] -> [n] listOfOnesWithSameLength = foldr constPrependOne []
If you have a list of [2, 4, 7, 2, 5] , you will get [1, 1, 1, 1, 1] when applying listOfOnesWithSameLength .
Then the function foldr (+) 0 is the other right button. This is equivalent to the sum function in Haskell; he summarizes the elements of the list.
So, create a function:
sum :: Num n => [n] -> n sum = foldr (+) 0
If you are now composing functions:
func = sum . listOfOnesWithSameLength
... you will get the resulting expression. Given a list, it creates a list of equal length, consisting of only one, and then summarizes the elements of this list. In other words, it behaves exactly the same as length , using only a slower algorithm. So the final function:
inefficientLength :: Num n => [a] -> n inefficientLength = sum . listOfOnesWithSameLength