Probably of interest to no one as I’m just dabbling but thought I’d share some code I’d written to try and compare to lists and return the items at the point they differ. First the embarrassing “why wont this language to what I want it to?” version:
module ListEx : sig val mismatch : 'a list -> 'a list -> 'a option * 'a option end = struct let mismatch a b = (* must: a_len <> b_len *) let find_missing a b = (* where list a is longer than b *) let find_missing_left a b = let len = List.length b in match List.findi ~f:(fun i _ -> i = len) a with | None -> assert false (* shouldn't happen as expected must be longer than found *) | Some (_, x) -> Some x, None (* the first expected item that has no match in found *) in (* where list b is longer than a *) let find_missing_right a b = match find_missing_left b a with | b, a -> a, b in if List.length a > List.length b then find_missing_left a b else find_missing_right a b in (* find the mismatching pair *) let mismatch' ab = (* true when a pair are unmatched *) let unmatched = function | a, b when a <> b -> true | _ -> false in match List.find ~f:unmatched ab with | None -> None, None (* OK all match *) | Some (a, b) -> Some a, Some b (* Some mismatch found *) in match List.zip a b with | None -> find_missing a b (* lists of different lengths *) | Some ab -> mismatch' ab (* list of same length *) end
Then the slightly less embarrassing version:
module ListEx : sig val mismatch : 'a list -> 'a list -> 'a option * 'a option end = struct let rec mismatch a b = match (List.hd a), (List.hd b) with | Some a', Some b' when a' = b' -> mismatch (List.tl_exn a) (List.tl_exn b) | x, y -> x, y end
That’s quite some line count difference. Unfortunately I’m finding I’m mainly writing code like the former at the moment.