include "List.aes" include "Option.aes" include "Pair.aes" namespace Set = record set('a) = { to_map : map('a, unit) } function new() : set('a) = { to_map = {} } function member(e : 'a, s : set('a)) : bool = Map.member(e, s.to_map) function insert(e : 'a, s : set('a)) : set('a) = { to_map = s.to_map{[e] = ()} } function delete(e : 'a, s : set('a)) : set('a) = { to_map = Map.delete(e, s.to_map) } function size(s : set('a)) : int = Map.size(s.to_map) function to_list(s : set('a)) : list('a) = List.map(Pair.fst, Map.to_list(s.to_map)) function from_list(l : list('a)) : set('a) = { to_map = Map.from_list(List.map((x) => (x, ()), l)) } function filter(p : 'a => bool, s : set('a)) : set('a) = from_list(List.filter(p, to_list(s))) function fold(f : ('a, 'b) => 'b, acc : 'b, s : set('a)) : 'b = List.foldr(f, acc, to_list(s)) function subtract(s1 : set('a), s2 : set('a)) : set('a) = filter((x) => !member(x, s2), s1) function intersection(s1 : set('a), s2 : set('a)) : set('a) = filter((x) => member(x, s2), s1) function intersection_list(sets : list(set('a))) : set('a) = List.foldr( intersection, Option.default(new(), List.first(sets)), Option.default([], List.tail(sets))) function union(s1 : set('a), s2 : set('a)) : set('a) = from_list(to_list(s1) ++ to_list(s2)) function union_list(sets : list(set('a))) : set('a) = List.foldr(union, new(), sets)