recursionocamlfold

Folding a list in OCaml


In OCaml, a typical fold function looks like this:

let rec fold (combine: 'a -> 'b -> 'b) (base: 'b) (l: 'a list) : 'b =
  begin match l with
  | [] -> base
  | x :: xs -> combine x (fold combine base xs)
  end

For those familiar with OCaml (unlike me), it should be pretty straightforward what it's doing.

I'm writing a function that returns true when all items in the list satisfy the condition: if condition x is true for all x in some list l. However I'm implementing the function using a fold function and I'm stuck. Specifically I don't know what the list should return. I know that ideally the condition should be applied to every item in the list but I have no idea how the syntax should look. x && acc works but it fails a very simply test (shown below)

let test () : bool =
  not (for_all (fun x -> x > 0) [1; 2; -5; -33; 2])
;; run_test "for_all: multiple elements; returns false" test

Here is my preliminary attempt. Any help is appreciated:

let  for_all (pred: 'a -> bool) (l: 'a list) : bool =
fold (fun(x:'a)(acc: bool)->  _?_&&_?_  )false l

Solution

  • let rec fold (combine: 'a -> 'b -> 'b) (base: 'b) (l: 'a list) : 'b =
      match l with
      | [] -> base
      | x::xs -> combine x (fold combine base xs)
    
    let for_all (pred: 'a -> bool) (lst: 'a list) =
      let combine x accum =
        (pred x) && accum
      in
      fold combine true lst
    

    Your combine function should not do x && base because elements of the list are not usually bool. You want your predicate function first evaluate the element to bool, then you "and" it with the accumulator.

    There is no need for begin and end in fold. You can just pattern match with match <identifier> with.

    There are two widespread types of fold: fold_left and fold_right. You're are using fold_right, which, basically, goes through the whole list and begins "combining" from the end of the list to the front. This is not tail-recursive.

    fold_left, on the other hand goes from the front of the list and combines every element with the accumulator right away. This does not "eat up" your stack by a number of recursive function calls.