From 842f60715b829a3238d734032101b70136d9575b Mon Sep 17 00:00:00 2001 From: h7x4 Date: Fri, 27 Sep 2024 21:42:26 +0200 Subject: [PATCH] util/binaryMerge: init --- flake.nix | 6 ++++++ util/binaryMerge.nix | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 util/binaryMerge.nix diff --git a/flake.nix b/flake.nix index d8d666a..39fce60 100644 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,13 @@ outputs = { self, nixpkgs-lib }: let inherit (nixpkgs-lib) lib; + + util = { + binaryMerge = import ./util/binaryMerge.nix; + }; in { + inherit util; + genAttrs = import ./src/genAttrs.nix lib; subtractLists = import ./src/subtractLists.nix lib; unique = import ./src/unique.nix lib; diff --git a/util/binaryMerge.nix b/util/binaryMerge.nix new file mode 100644 index 0000000..adf94d4 --- /dev/null +++ b/util/binaryMerge.nix @@ -0,0 +1,28 @@ +# binaryMerge :: (b -> b -> b) -> [b] -> b | null +merge: +list: + +let + # `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end` + # Type: Int -> Int -> b + binaryMerge' = start: end: + # assert start < end; # Invariant + if end - start >= 2 then + let + # If there's at least 2 elements, split the range in two, recurse on each part and merge the result + # The invariant is satisfied because each half will have at least 1 element + firstHalf = binaryMerge' start (start + (end - start) / 2); + secondHalf = binaryMerge' (start + (end - start) / 2) end; + in merge firstHalf secondHalf + else + # Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly + builtins.elemAt list start; +in +if list == [ ] then + # Calling binaryMerge as below would not satisfy its invariant + null +else + binaryMerge' 0 (builtins.length list) + +# Source: taken and modified from +# https://github.com/NixOS/nixpkgs/blob/3cae63521d93eb2fb0aba28218ca9b00150ffdc1/lib/attrsets.nix#L1488-L1507