{ lib }: with lib; { recursiveMergeAttrs = a: b: let commonAttrs = intersectLists (attrNames a) (attrNames b); aAttrs = subtractLists (attrNames a) commonAttrs; bAttrs = subtractLists (attrNames b) commonAttrs; aSide = (filterAttrs (k: v: elem k aAttrs) a); bSide = (filterAttrs (k: v: elem k bAttrs) b); common = (foldr (a: b: a // b) {} (map (k: { ${k} = a.${k} // b.${k}; }) commonAttrs)); in aSide // bSide // common; }