Pregunta

¿Es posible escribir funciones con parámetros de entrada tipificados dinámicamente? Intenté la coincidencia de patrones, pero aparentemente no funciona así.

Deseo hacer algo como esto:

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

Gracias.

¿Fue útil?

Solución

StandardML es un lenguaje estricto y estático. Por lo tanto, no puede tener una función que acepte un int en el primer caso y una cadena en el segundo. El error que obtienes es

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)

Si desea tener un caso que es una cadena y un caso que es un int, puede crear un nuevo tipo, un " union etiquetada " (también conocido como " discriminación discriminada "), que está diseñado para ser fácil de usar con la coincidencia de patrones. Se vería así:

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

Por supuesto, es posible que desee encontrar un nombre más apropiado para este tipo de envoltura, algo que tenga sentido en el contexto de su programa. También tenga en cuenta que la anotación de tipo en n no es realmente necesaria; sería más idiomático escribir

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

Además, el compilador le dirá que ha dejado un caso descubierto: ¿Qué sucede si el primer argumento es un número entero que no es igual a cero?

Finalmente, no está realmente claro a qué te refieres con la comparación b > n , ¿qué aspecto de las dos cadenas quisiste comparar? Veo que cuando comparo dos cadenas en SML, veo una comparación lexicográfica (también conocida como alfabética). ¿Es eso lo que querías?

Otros consejos

Para elaborar un poco, suponga que tiene dos argumentos, cada uno de los cuales podría ser una cadena o un entero, y si tiene dos cadenas desea la cadena lexicográficamente más pequeña, si tiene una cadena desea esa cadena, y si tienes dos enteros no puedes devolver una cadena. ¿Qué haces? Devuelva un valor de tipo opción de cadena (busque la opción , SOME y NONE en 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 función firstStr tiene tipo

string_or_int * string_or_int -> string option

La forma más rápida de convertirse en un programador de ML competente es aprender a pensar sobre los tipos primero . Si, por ejemplo, lo que realmente quería era una función de tipo string option * string - > string , no necesitarías escribirlo tú mismo; la función incorporada getOpt hace eso. Por otro lado, suena como si quisieras la opción de cadena * string - > cadena , para que puedas escribir

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

y no necesita un constructor de valor SOME o una opción en el resultado.

Las variantes polimorfas en OCaml tienen más de La propiedad dinámica que busca. Puede echar un vistazo si lo desea, OCaml y SML son idiomas muy cercanos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top