La única gran razón por la que todavía se requiere abstype
es para aplicaciones realistas es imprimir bastante bien. Esto se refiere a la intersección de SML/NJ y Poly/ML - No sé cómo funciona Mlton en este aspecto (no tiene un nivel adecuado).
La tarea es simple: defina un tipo de datos abstracto (uno que no filtre la igualdad) y proporcione una impresora bonita para él. El único (cuasi-portátil) respuesta que conozco utiliza llanura de edad abstype con estilo SML'90 no opaca la firma coincidente:
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
debe imprimir {42}[1]
en este ejemplo divertido - las líneas específicas del compilador necesitan ser no comentado Esto definitivamente está fuera del estándar SML'97, o intentos posteriores en ML'2000 y más allá, pero funciona tanto para SML/NJ como para Poly/ML, ya que todavía están disponibles en la actualidad. En cierto sentido, se ve una cultura SML'90 anterior y anterior a SML brillando, incluso un poco de pirateo de LPL hasta niveles avanzados. (Los post-ludes anteriores a la definición de estructura se pueden convertir en envoltorios graciosos que invocan el nivel SML en tiempo de compilación de una manera que funcione para ambos, haciendo que las fuentes parezcan portátiles.)
Tenga en cuenta que para aplicaciones como Isabelle , HOL4, ProofPower, toplevel ML, la impresión bonita es indispensable, independientemente de lo que digan los escritores estándar de SML.
Aquí hay dos versiones más que están más en línea con SML'97 y firma opaca a juego :>
pero fallan a trabajar de manera 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));
*)
espero que tengo todos los casos impares derecha. La indicación "no pp" es diferente para diferentes SML: Poly/ML imprime la representación original, mientras que SML/NJ no imprime nada (solo un guión como marcador de posición). El tipo opaco "sin etiquetar" es particularmente desagradable: en Poly/ML anulará la impresora bonita para int, pero para SML/NJ no hace nada, lo que también es malo.
Enlace reparado ahora. :) –
Lo único que puedes hacer con abstype que no puedes con los módulos (al menos en SML'97 simple) es definir un tipo de resumen localmente dentro de un '' let''. Pero eso no es algo que nadie haya sentido como una necesidad ardiente ... –