Skip to content

Instantly share code, notes, and snippets.

@ENAML
Created February 8, 2019 04:52
Show Gist options
  • Save ENAML/5a827bf3f725d5e3bd97cb6ae484f1b6 to your computer and use it in GitHub Desktop.
Save ENAML/5a827bf3f725d5e3bd97cb6ae484f1b6 to your computer and use it in GitHub Desktop.
simple diffing of two ordered maps
open Base
let left x = `Left(x)
let right x = `Right(x)
let change a b = `Change(a, b)
let rec diff_seqs ?(acc = []) s0 s1 =
let cmp = Poly.compare in
let v_eq = Poly.equal in
match Sequence.next s0, Sequence.next s1 with
| None, None -> List.rev acc
| Some(x0, s0_next), None -> diff_seqs s0_next s1 ~acc:((left x0)::acc)
| None, Some(x1, s1_next) -> diff_seqs s0 s1_next ~acc:((right x1)::acc)
| Some(x0, s0_next), Some(x1, s1_next) ->
let (k0, v0), (k1, v1) = x0, x1 in
let k_diff = cmp k0 k1 in
if k_diff < 0 then (* left is lower *)
diff_seqs s0_next s1 ~acc:((left x0)::acc)
else if k_diff > 0 then (* right is lower *)
diff_seqs s0 s1_next ~acc:((right x1)::acc)
else begin (* equal *)
if v_eq v0 v1 then
diff_seqs s0_next s1_next ~acc:acc
else
diff_seqs s0_next s1_next ~acc:((change x0 x1)::acc)
end
(* simple diff_seqs test *)
let () =
let open Sequence in
let s0 = of_list [(0, "a"); (1, "b"); (2, "c"); (3, "m"); (4, "n"); (5, "m")] in
let s1 = of_list [(0, "a"); (1, "c"); (2, "c"); (4, "n"); (5, "m"); (6, "s")] in
assert begin
Poly.equal
(diff_seqs s0 s1)
[`Change ((1, "b"), (1, "c")); `Left (3, "m"); `Right (6, "s")]
end
let diff_map map0 map1 =
let seq0, seq1 = Map.(to_sequence map0, to_sequence map1) in
diff_seqs ~acc:[] seq0 seq1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment