SML / NJ - Pattern Matching eine dynamische Typisierung
-
05-07-2019 - |
Frage
Ist es möglich, Funktionen mit dynamisch typisierten Eingabeparametern zu schreiben? Ich habe versucht, Pattern-Matching, aber anscheinend ist es nicht wie das funktioniert.
Ich möchte etwas tun:
fun firstStr (0,n:string) = n
| firstStr (b:string,n:string) = if b>n then n else b;
Danke.
Lösung
StandardML ist eine strenge, statisch typisierte Sprache. Daher können Sie nicht eine Funktion haben, die in der zweiten einen int im ersten Fall und einen String akzeptiert. Der Fehler, den Sie erhalten, ist
this clause: string * string -> 'Z
previous clauses: int * string -> 'Z
in declaration:
firstStr =
(fn (0,<pat> : string) => n
| (<pat> : string,<pat> : string) => if <exp> > <exp> then n else b)
Wenn Sie einen Fall haben wollen, die eine Zeichenfolge und ein Fall ist, die ein int ist, können Sie eine neue Art zu machen, ein „ getaggt Vereinigung “(auch bekannt als‚diskriminierte Union‘), die leicht gestaltet ist mit Mustervergleich zu verwenden. Es würde wie folgt aussehen:
datatype Wrapper = Int of int
| String of string
fun firstStr(Int 0, n:string) = n
| firstStr(String b, n:string) = if b>n then n else b
Natürlich mögen Sie vielleicht etwas passenderen Namen für diesen Wrapper-Typen zu finden, etwas, den Sinn im Rahmen des Programms macht. Bitte beachten Sie auch, dass die Art Anmerkung auf n
ist nicht wirklich notwendig; es würde mehr idiomatische schreiben
fun firstStr(Int 0, n) = n
| firstStr(String b, n) = if b>n then n else b
Darüber hinaus wird der Compiler Ihnen sagen, Sie verlassen haben einen Fall aufgedeckt:? Was ist, wenn das erste Argument eine ganze Zahl nicht gleich Null
Schließlich ist es nicht wirklich klar, was man durch den Vergleich b>n
bedeuten, was Aspekt der beiden Strings wollen Sie vergleichen? Ich sehe, dass, wenn ich zwei Strings in SML vergleichen, ich sehe einen lexikographischen (aka alphabetisch) Vergleich. Ist das, was Sie wollen?
Andere Tipps
Um ein wenig zu erarbeiten: Angenommen, Sie zwei Argumente haben, von denen jede eine Zeichenfolge oder eine ganze Zahl sein könnte, und wenn Sie zwei Strings haben möchten Sie die lexikographisch kleinere Zeichenfolge, wenn Sie eine Zeichenfolge haben wollen Sie diese Zeichenfolge, und wenn Sie zwei ganzen Zahlen haben, können Sie nicht einen String zurück. Wie geht's? Gibt einen Wert vom Typ string option
(aufblicken option
, SOME
und NONE
unter http: //www.standardml .org / Basis / option.html ):
datatype string_or_int = String of string
| Int of int
fun firstStr(String a, String b) = SOME (if a < b then a else b)
| firstStr(String a, Int _ ) = SOME a
| firstStr(Int _, String b) = SOME b
| firstStr(Int _, Int _ ) = NONE
Funktion firstStr
hat Typ
string_or_int * string_or_int -> string option
Der schnellste Weg, ein geübter ML Programmierer zu werden ist zu lernen Typen zuerst denken . Wenn zum Beispiel, was Sie wirklich wollte, war eine Funktion vom Typ string option * string -> string
, würden Sie es nicht selbst schreiben müssen; die eingebaute Funktion getOpt
das tut. Auf der anderen Seite, es klingt wie Sie string option * string -> string
wollen, so können Sie schreiben
fun firstStr(SOME a, b) = if a < b then a else b
| firstStr(NONE, b) = b
und Sie nicht einen SOME
Wert Konstruktor oder einen option
Typen auf dem Ergebnis‘müssen.
polymorphe Varianten in OCaml haben mehr die dynamische Eigenschaft, die Sie suchen. Sie können einen Blick, wenn Sie wollen, OCaml und SML sind ganz in der Nähe Sprachen.