2016-08-30 1 views
5

J'ai une question peut-être inhabituelle, mais comment correspond à une fonction en F # en utilisant la correspondance de modèle?Motif correspondant à une fonction en F #

Imaginez ce qui suit:
J'ont des signatures de fonctions multiples, qui seront utilisés plusieurs fois, comme:

binary function: int -> int -> int 
unary function: int -> int 
boolean function: int -> int -> bool 
... 

Imaginez maintenant que la fonction evaluate, qui se prend une fonction f. La signature de fdoit être être l'un des éléments énumérés ci-dessus. Comment faire correspondre un tel cas?


J'ai essayé les choses suivantes:
test n ° 1: Utilisation délégués et syndicats:

type UnaryFunction = delegate of int -> int 
type BinaryFunction = delegate of (int -> int) -> int 
type BooleanFunction = delegate of (int -> int) -> bool 

type Functions = 
    | Unary of UnaryFunction 
    | Binary of BinaryFunction 
    | Boolean of BooleanFunction 

// ... 

let evaluate f = // signature: Functions -> string 
    match f with 
    | Unary u -> 
     let test_result = u.Invoke 3 
     sprintf "the result of the unary function is %d" test_result 
    | Binary b -> 
     let test_result = b.Invoke 315 42 
     sprintf "the result of the binary function is %d" test_result 
    | Boolean o -> 
     let test_result = o.Invoke 315 42 
     if test_result then "yeah" else "nope" 

test n ° 2: Utilisation correspondance de motif de type et les délégués:

type UnaryFunction = delegate of int -> int 
type BinaryFunction = delegate of (int -> int) -> int 
type BooleanFunction = delegate of (int -> int) -> bool 

let evaluate f = 
    match f with 
    | ?: UnaryFunction as u -> 
     let test_result = u.Invoke 3 
     sprintf "the result of the unary function is %d" test_result 
    | ?: BinaryFunction as b -> 
     let test_result = b.Invoke 315 42 
     sprintf "the result of the binary function is %d" test_result 
    | ?: BooleanFunction as o -> 
     let test_result = o.Invoke 315 42 
     if test_result then "yeah" else "nope" 
    | _ -> "invalid function type" 


Le problème avec ces exemples est que délégués de ... seront appariés au lieu de fonctions réelles. Je voudrais voir somethink comme ceci:

let evaluate f = 
    match f with 
    | ?: (int -> int) as u -> 
     let test_result = u 3 
     sprintf "the result of the unary function is %d" test_result 
    | ?: ((int -> int) -> int) as b -> 
     let test_result = b 315 42 
     sprintf "the result of the binary function is %d" test_result 
    | ?: ((int -> int) -> bool) as o -> 
     let test_result = o 315 42 
     if test_result then "yeah" else "nope" 
    | _ -> "invalid function type" 

Est-ce que F # a une syntaxe spéciale pour le filtrage de fonction?
Et si non, pourquoi? Ai-je manqué quelque chose, ou n'est-il pas aussi important de pouvoir faire correspondre des fonctions comme n'importe quoi d'autre, puisqu'il s'agit d'un langage fonctionnel?

+4

Pourquoi avez-vous besoin d'utiliser des délégués plutôt que des fonctions? –

+0

@FyodorSoikin: Je l'ai essayé précédemment, mais en raison d'une faute de frappe (que je ne savais pas à ce moment-là), je ne pouvais pas définir les types comme des fonctions. J'ai donc pensé que c'était impossible:/ – Unknown6656

Répondre

10

Au lieu d'utiliser les délégués, simplement définir le travail en utilisant les fonctions directement:

type UnaryFunction = int -> int 
type BinaryFunction = int -> int -> int 
type BooleanFunction = int -> int -> bool 

type Functions = 
    | Unary of UnaryFunction  
    | Binary of BinaryFunction 
    | Boolean of BooleanFunction 

// ... 

let evaluate f = // signature: Functions -> string 
    match f with 
    | Unary u -> 
     let test_result = u 3 
     sprintf "the result of the unary function is %d" test_result 
    | Binary b -> 
     let test_result = b 315 42 
     sprintf "the result of the binary function is %d" test_result 
    | Boolean o -> 
     let test_result = o 315 42 
     if test_result then "yeah" else "nope" 

Une fois que vous avez fait cela, vous pouvez les appeler au besoin (comme ci-dessous, montrant la sortie FSI):

> evaluate (Unary (fun x -> x + 3));; 
val it : string = "the result of the unary function is 6" 

> let someBinaryFunction x y = x * y;; 
val someBinaryFunction : x:int -> y:int -> int 

> Binary someBinaryFunction |> evaluate;; 
val it : string = "the result of the binary function is 13230" 
+1

** Je vous aime, Monsieur! ** D'une certaine manière, cela n'a pas fonctionné avant pour moi (j'ai détecté que c'était dû à une faute de frappe). J'ai donc pensé que ce n'était pas possible ... – Unknown6656