Die stdlib Set
kann nicht polymorph sein, da ihr Typkonstruktor keine Argumente hat. Sie können jedoch map
aus beliebiger Menge zu beliebigem Satz mit einem Funktor ausdrücken:
module MapSet (S1:Set.S) (S2:Set.S) = struct
let map f a = S1.fold (fun elt set -> S2.add (f elt) set) a S2.empty
end
Die Nutzung:
module IntSet = Set.Make (struct type t = int let compare = compare end)
module StringSet = Set.Make (String)
module MapSI = MapSet (StringSet) (IntSet)
# IntSet.elements (MapSI.map String.length (StringSet.of_list ["a"; "zonk"; "blart"]));;
- : IntSet.elt list = [1; 4; 5]
Wie Sie sehen können, ist es einfach, aber ausführlich und ‚namey‘.
Eine andere Alternative ist die Verwendung einer ('a, unit) Hashtbl
als veränderbare Menge, die polymorphe Gleichheit unter der Haube (mit allen üblichen Nachteilen) verwenden wird. Sie können Ihre eigenen map
Betrieb leicht implementieren:
let map_keys f tbl =
let new_tbl = Hashtbl.create (Hashtbl.length tbl) in
Hashtbl.iter (fun k v -> Hashtbl.replace new_tbl (f k) v) tbl;
new_tbl
bewusst sein, dass Hashtbl
nicht der schlimmste Fall garantiert nicht vorsehen, dass Set
der Fall ist, oder effiziente Vereinigung/diff/Kreuzung Operationen.
nette Lösung. Eine Frage: Was meinst du mit "Hashtbl bietet nicht die Worst-Case-Garantien, die Set tut"? –
Für 'Set' sind' mem', 'add', etc logarithmisch in der Größe des Satzes. Der schlimmste Fall von Hashtbl ist O (n), obwohl es unwahrscheinlich ist, dass er auftritt. – gsg