2010-12-01 8 views
3

Est-il possible d'utiliser les fonctions dans les syndicats discriminés? Je cherche à faire quelque chose comme ceci:Fonctions syndicats F # Discriminé

Type Test<'a> = Test of 'a-> bool

Je sais que cela est possible en utilisant Haskell newtype et je me demandais ce que l'équivalent en F # serait.

Merci.

+0

La confusion est juste que F # nécessite des parenthèses superflues autour du type de fonction ''a -> bool'. –

Répondre

4

Comme une extension sur la réponse de Desco vous pouvez appliquer la fonction rentrée dans test avec correspondance de motif:

type Test<'a> = Test of ('a -> bool) 

// let applyTest T x = match T with Test(f) -> f x 
// better: (as per kvb's comment) pattern match the function argument 
let applyTest (Test f) x = f x 

Exemple:

// A Test<string> 
let upperCaseTest = Test (fun (s:string) -> s.ToUpper() = s) 

// A Test<int> 
let primeTest = 
    Test (fun n -> 
     let upper = int (sqrt (float n)) 
     n > 1 && (n = 2 || [2..upper] |> List.forall (fun d -> n%d <> 0)) 
    ) 

En FSI:

> applyTest upperCaseTest "PIGSMIGHTFLY";; 
val it : bool = true 
> applyTest upperCaseTest "PIGSMIgHTFLY";; 
val it : bool = false 
> [1..30] |> List.filter (applyTest primeTest);; 
val it : int list = [2; 3; 5; 7; 11; 13; 17; 19; 23; 29] 
+1

Notez que puisqu'il n'y a qu'un seul cas dans l'union discriminée vous pouvez sans risque match de motif sur le côté gauche de 'applyTest' afin que vous n'avez pas l'identifiant de sens' T' qui encombrent les choses: 'laisser applyTest (Test f) x = fx'. – kvb

+0

@kvb: sympa! J'ai oublié que les arguments de fonction sont aussi des motifs. J'ai mis à jour mon message. – cfern

5
type Test<'A> = Test of ('A -> bool) 
+0

Question rapide. Comment appliquez-vous réellement la fonction d'une telle liaison? – Ochowie

+1

Extrayez la fonction avec quelque chose comme 'let (Test f) = Test (fun _ -> true)' pour le lier à 'f'. –