Question

Est-il possible d'écrire des fonctions avec des paramètres d'entrée typés dynamiquement? J'ai essayé la correspondance de motif, mais apparemment, cela ne fonctionne pas comme ça.

Je souhaite faire quelque chose comme ceci:

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

Merci.

Était-ce utile?

La solution

StandardML est un langage strict, typé de manière statique. Par conséquent, vous ne pouvez pas avoir une fonction qui accepte un int dans le premier cas et une chaîne dans le second. L'erreur que vous obtenez est

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 vous souhaitez avoir un cas qui est une chaîne et un cas qui est un entier, vous pouvez créer un nouveau type, un " union marquée " (aka "discriminated union"), qui est conçu pour être facile à utiliser avec un filtrage par motif. Cela ressemblerait à ceci:

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

Bien sûr, vous voudrez peut-être trouver un nom plus approprié pour ce type Wrapper, ce qui est logique dans le contexte de votre programme. Notez également que l'annotation de type sur n n'est pas vraiment nécessaire; il serait plus idiomatique d'écrire

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

De plus, le compilateur vous dira que vous avez laissé un cas découvert: que se passera-t-il si le premier argument est un entier différent de zéro?

Enfin, vous ne savez pas vraiment ce que vous entendez par comparaison b > n . Quel aspect des deux chaînes voulez-vous comparer? Je vois que lorsque je compare deux chaînes dans SML, je vois une comparaison lexicographique (ou alphabétique). Est-ce ce que tu voulais?

Autres conseils

Pour en dire un peu plus, supposons que vous ayez deux arguments, chacun pouvant être une chaîne ou un entier, et si vous avez deux chaînes, vous voulez la chaîne lexicographiquement plus petite, si vous avez une chaîne vous voulez cette chaîne, et Si vous avez deux entiers, vous ne pouvez pas retourner de chaîne. Que faire? Renvoie une valeur de type chaîne option (recherche option , SOME et NONE à 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 fonction firstStr a le type

string_or_int * string_or_int -> string option

Le moyen le plus rapide de devenir un programmeur expérimenté en ML consiste à apprendre à penser aux types en premier . Si par exemple, ce que vous vouliez vraiment était une fonction de type option de chaîne * chaîne - > chaîne , vous n’auriez pas besoin de l’écrire vous-même; la fonction intégrée getOpt fait cela. Par contre, il semble que vous souhaitiez l'option de chaîne * string - > chaîne , vous pouvez donc écrire

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

et vous n'avez pas besoin d'un constructeur de valeur SOME ou d'un type option sur le résultat.

Les variantes polymorphes dans OCaml ont plusieurs autres options. la propriété dynamique que vous recherchez. OCaml et SML sont des langages très proches.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top