with builtins; rec { fold = op: nul: list: if list == [ ] then nul else op (head list) (fold op nul (tail list)); concat = fold (x: y: x + y) ""; and = fold (x: y: x && y) true; flatten = x: if isList x then fold (x: y: (flatten x) ++ y) [ ] x else [ x ]; sum = foldl' (x: y: add x y) 0; hasSuffix = ext: fileName: let lenFileName = stringLength fileName; lenExt = stringLength ext; in !(lessThan lenFileName lenExt) && substring (sub lenFileName lenExt) lenFileName fileName == ext; # Split a list at the given position. splitAt = pos: list: if pos == 0 then { first = [ ]; second = list; } else if list == [ ] then { first = [ ]; second = [ ]; } else let res = splitAt (sub pos 1) (tail list); in { first = [ (head list) ] ++ res.first; second = res.second; }; # Stable merge sort. sortBy = comp: list: if lessThan 1 (length list) then let split = splitAt (div (length list) 2) list; first = sortBy comp split.first; second = sortBy comp split.second; in mergeLists comp first second else list; mergeLists = comp: list1: list2: if list1 == [ ] then list2 else if list2 == [ ] then list1 else if comp (head list2) (head list1) then [ (head list2) ] ++ mergeLists comp list1 (tail list2) else [ (head list1) ] ++ mergeLists comp (tail list1) list2; id = x: x; const = x: y: x; range = first: last: if first > last then [ ] else genList (n: first + n) (last - first + 1); }