{lib, ...}: let merge = merge_list: let head_of_merge = builtins.head merge_list; in if builtins.isAttrs head_of_merge then builtins.zipAttrsWith ( name: values: let head_value = builtins.head values; in if builtins.isString head_value then builtins.concatStringsSep "" values else if builtins.isList head_value then builtins.concatLists values else if builtins.isAttrs head_value then merge values else builtins.head values ) merge_list else if builtins.isString head_of_merge then builtins.concatStringsSep "" merge_list else if builtins.isList head_of_merge then builtins.concatLists merge_list else builtins.head merge_list; # Tests ## Strings a = { a = '' This is some ''; }; b = { a = '' example text ''; }; c = { a = "(which is nice)"; }; ## Lists d = { a = ["element1" "element2"]; }; e = { a = [["elment3" "elemnt4"]]; }; f = { a = ["elemnt5"]; }; ## Pure strings g = "This"; h = "is"; i = "some example text"; j = '' (with a newline) ''; ## Pure lists k = ["element1"]; l = ["element2" "element3"]; m = ["element4"]; ## Prepared tests tests = { tests = []; # Uncomment to actually run the tests test_strings = { expr = merge [a b c]; expected = {a = "This is some\nexample text\n(which is nice)";}; }; test_lists = { expr = merge [d e f]; expected = {a = ["element1" "element2" ["elment3" "elemnt4"] "elemnt5"];}; }; test_pure_strings = { expr = merge [g h i j]; expected = "Thisissome example text(with a newline)\n"; }; test_pure_lists = { expr = merge [k l m]; expected = ["element1" "element2" "element3" "element4"]; }; }; in { inherit merge; result = lib.debug.runTests tests; }