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
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.