I need to write a function twoMin: int list → int * int using foldl that returns the two smallest values (not elements) of a list. You may assume that the list contains at least two elements with different values.
let rec foldl f l acc = match l with
| [] -> acc
| x :: xs -> foldl f xs (f x acc)
let twoMin lst =
match lst with
| [] | [_] -> failwith "List must contain at least two elements with different
values."
| x :: y :: rest ->
let initial_acc = if x < y then (x, y) else (y, x) in
let (min1, min2) = foldl (fun a b -> if b < fst a then (b, fst a) else if b < snd
a then (fst a, b) else a) rest initial_acc in
(min1, min2)
I keep getting error and I do not know what is wrong with the code.
You're close.
The accumulator you're passing to
foldlis a tuple of two values. This is fine. However, the result of the function you pass tofoldlmust have the same type as the accumulator. If we take your code and change some of the names:We can see that you're treating each element of the list as the accumulator, and vice versa.
Using
fstandsndlike this is annoying when we can just use pattern-matching.Of course, pattern-matching that tuple, then just rebuilding it and returning it immediately is pointless.
Also, your confusion may be aided by your definition of a left fold, which differs from
List.fold_left. Try instead: