Domanda

È possibile scrivere funzioni con parametri di input tipizzati dinamicamente? Ho provato la corrispondenza dei modelli, ma a quanto pare non funziona in questo modo.

Vorrei fare qualcosa del genere:

fun firstStr (0,n:string) = n
  | firstStr (b:string,n:string) = if b>n then n else b;

Grazie.

È stato utile?

Soluzione

StandardML è un linguaggio rigorosamente tipizzato staticamente. Pertanto, non è possibile avere una funzione che accetta un int nel primo caso e una stringa nel secondo. L'errore che ricevi è

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)

Se vuoi avere un caso che è una stringa e un caso che è un int, puoi creare un nuovo tipo, un " taggato unione " (aka "unione discriminata"), progettata per essere facile da usare con la corrispondenza dei motivi. Sembrerebbe così:

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

Naturalmente, potresti voler trovare un nome più appropriato per questo tipo di wrapper, qualcosa che ha senso nel contesto del tuo programma. Si noti inoltre che l'annotazione del tipo su n non è realmente necessaria; sarebbe più idiomatico scrivere

fun firstStr(Int 0,    n) = n
  | firstStr(String b, n) = if b>n then n else b

Inoltre, il compilatore ti dirà che hai lasciato un caso scoperto: cosa succede se il primo argomento è un numero intero non uguale a zero?

Infine, non è davvero chiaro cosa intendi con il confronto b > n , quale aspetto delle due stringhe vuoi confrontare? Vedo che quando confronto due stringhe in SML, vedo un confronto lessicografico (aka alfabetico). È quello che volevi?

Altri suggerimenti

Per elaborare un po ', supponi di avere due argomenti, ognuno dei quali potrebbe essere una stringa o un numero intero, e se hai due stringhe vuoi la stringa lessicograficamente più piccola, se hai una stringa vuoi quella stringa, e se hai due numeri interi non puoi restituire una stringa. cosa fai? Restituisce un valore di tipo opzione stringa (cerca opzione , SOME e NONE in 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

La funzione firstStr ha il tipo

string_or_int * string_or_int -> string option

Il modo più veloce per diventare un abile programmatore ML è imparare a pensare prima ai tipi . Se per esempio, quello che volevi veramente era una funzione di tipo stringa opzione * stringa - > stringa , non dovresti scriverlo tu stesso; la funzione integrata getOpt lo fa. D'altra parte, sembra che tu voglia l'opzione string * string - > stringa , così puoi scrivere

fun firstStr(SOME a, b) = if a < b then a else b
  | firstStr(NONE,   b) = b

e non è necessario un SOME costruttore di valori o un'opzione sul risultato.

Varianti polimorfiche in OCaml hanno più di la proprietà dinamica che stai cercando. Puoi dare un'occhiata se vuoi, OCaml e SML sono lingue molto vicine.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top