L'unico grande motivo per cui lo abstype
è ancora necessario è che per le applicazioni realistiche è sufficiente la stampa. Questo si riferisce all'intersezione tra SML/NJ e Poly/ML - Non so come funziona Mlton in questo senso (non ha un buon livello).
Il compito è semplice: definire un tipo di dati astratto (uno che non perde l'uguaglianza) e fornire una stampante abbastanza carina per questo. L'unica (quasi-portatile) risposta che so che usa plain-old abstype con stile SML'90 non opachi firma abbinamento:
structure A1:
sig
type t val a: t val b: t -> t val print: t -> string
end =
struct
abstype t = A of int
with
val a = A 42
fun b (A i) = A (i + 1)
fun print (A i) = "{"^Int.toString i^"}[1]"
end
end;
(* works for Poly/ML 5.3, 5.4, 5.5:
PolyML.addPrettyPrinter (fn depth => fn pretty => fn x => PolyML.PrettyString (A1.print x));
*)
(* works for SML/NJ 110.xx:
CompilerPPTable.install_pp ["A1", "t"] (fn pps => fn x => PrettyPrint.string pps (A1.print x));
*)
A1.a
dovrebbe stampare {42}[1]
in questo esempio divertente - le linee specifiche compilatore bisogno essere non commentato Questo è decisamente al di fuori dello standard SML'97, o tentativi successivi a ML'2000 e oltre, ma funziona sia per SML/NJ che per Poly/ML, poiché sono ancora disponibili oggi. In un certo senso, si vedono alcune vecchie SML'90 e una cultura pre-SML che sfolgorano, persino un po 'di hacking toplevel di LISP. (I precedenti post-ludi alla definizione della struttura possono essere trasformati in buffi wrapper che invocano la SML in fase di compilazione in un modo che funziona per entrambi, rendendo così le sorgenti comparse.)
Nota che per applicazioni come Isabelle , HOL4, ProofPower, toplevel ML la stampa carina è indispensabile, qualunque cosa possano dire gli scrittori SML standard.
Qui ci sono altre due versioni che sono più in linea con SML'97 e firma opaco corrispondenza :>
ma non riescono a lavorare in modo uniforme:
structure A2 :>
sig
type t val a: t val b: t -> t val print: t -> string
end =
struct
datatype t = A of int
val a = A 42
fun b (A i) = A (i + 1)
fun print (A i) = "{"^Int.toString i^"}[2]"
(* works, but non-portable:
val _ =
PolyML.addPrettyPrinter (fn depth => fn pretty => fn x => PolyML.PrettyString (print x))
*)
(* does not work (scope problem -- no pp):
val _ =
CompilerPPTable.install_pp ["A2", "t"] (fn pps => fn x => PrettyPrint.string pps (A2.print x));
*)
end;
(* does not work (no pp):
PolyML.addPrettyPrinter (fn depth => fn pretty => fn x => PolyML.PrettyString (A2.print x));
*)
(* does not work (no pp):
CompilerPPTable.install_pp ["A2", "t"] (fn pps => fn x => PrettyPrint.string pps (A2.print x));
*)
structure A3 :>
sig
type t val a: t val b: t -> t val print: t -> string
end =
struct
type t = int
val a = 42
fun b i = i + 1
fun print i = "{"^Int.toString i^"}[3]"
(* does not work (overrides pp for int):
val _ =
PolyML.addPrettyPrinter (fn depth => fn pretty => fn x => PolyML.PrettyString (print x))
*)
(* does not work (scope problem -- no pp)
val _ = CompilerPPTable.install_pp ["A2", "t"] (fn pps => fn x => PrettyPrint.string pps (A2.print x));
*)
end;
(* works:
PolyML.addPrettyPrinter (fn depth => fn pretty => fn x => PolyML.PrettyString (A3.print x));
*)
(* does not work (no pp):
CompilerPPTable.install_pp ["A3", "t"] (fn pps => fn x => PrettyPrint.string pps (A3.print x));
*)
Spero che ho tutti i casi strani destra. La "no pp" è diversa per le diverse SML: Poly/ML stampa la rappresentazione originale, mentre SML/NJ non stampa nulla (solo un trattino come segnaposto). Il tipo opaco "non contrassegnato" è particolarmente sgradevole: in Poly/ML sovrascrive la pretty-printer per int, ma per SML/NJ non fa nulla, il che è anche negativo.
Collegamento riparato ora. :) –
L'unica cosa che puoi fare con l'abstype che non puoi con i moduli (almeno in SML'97) è la definizione di un tipo astratto localmente all'interno di '' let''. Ma non è qualcosa che qualcuno abbia mai sentito un bisogno ardente di ... –