To build a list using fold it is probably easier to use fold_right
, because you can only prepend elements to a list efficiently, and thus you should start building the list from the right, which is what fold_right
does. (You can also use fold_left
but then you need to reverse the list in an additional step or use the expensive list concatenation.)
A more simple example for building a list with fold_right
would be to build a list of sums of elements of a list starting at the end of the list, e.g., sums [a; b; c]
gives [a+b+c; b+c; c]
. The code looks as follows.
let sums = List.fold_right
(fun x ys ->
match ys with
| [] -> [x]
| hd :: tl -> (x + hd) :: ys)
[1; 2; 3; 4; 5]
[]
What the inner function does is to take the first element of the already built list and add it to the current element. (Keep in mind that the elements are visited from right to left.) Then the sum is added to the front of the already existing list.
Defining the non_decresing
function works in a similar way. We have to work, however, with nested lists, which makes things a bit more complicated. The code is as follows.
let non_decreasing xs =
List.fold_right
(fun x outer ->
match outer with
| [] -> [[x]]
| outer_hd :: outer_tl ->
if x <= List.hd outer_hd then
(x :: outer_hd) :: outer_tl
else
[x] :: outer)
xs
[]
Again, we are building the list from right to left, but this time we have to decide to which of the two lists, we add the new element. Either we add it to the head of the outer list or we add a new list, containing just the current element, to the beginning of the outer list.