2012-06-01 13 views
20

Esiste un modo standard per combinare logicamente i predicati in F #? Per esempio, diciamo che ho isCar x e isBlue x poi voglio qualcosa che mi dà:Combinazione di predicati in F #

let isBlueCar x = isCar x && isBlue x 

Ma utilizzando una sorta di composizione, piuttosto che l'invocazione, forse come:

let isBlueCar x = isCar && isBlue 

Preferibilmente, che qualcosa sarebbe in grado di accettare un numero ampio/arbitrario di predicati.

risposta

21

È possibile definire un combinatore.

let (<&>) f g = (fun x -> f x && g x) 

quindi fare

let isBlueCar = isCar <&> isBlue 
+3

... ed è davvero così facile, eh? Adoro F #. – GregRos

+0

@GregRos - controlla FParsec (http://www.quanttec.com/fparsec), una libreria di analisi splendidamente realizzata utilizzando l'approccio combinatori :-) – theburningmonk

+0

Ho: P Sto scrivendo il codice su di esso mentre parliamo:) – GregRos

2

È questo quello che stai cercando?

> let (&&<) a b x = a x && b x 

val (&&<) : ('a -> bool) -> ('a -> bool) -> 'a -> bool 

> let isBlueCar = isCar &&< isBlue 

val isBlueCar : (int -> bool) 
4

Si potrebbe fare qualcosa di simile al seguente:

let predicates = [isCar; isBlue] 
let isBlueCar x = predicates |> List.forall (fun predicate -> predicate x) 

Più in generale:

let combinePredicates predicates = 
    fun x -> predicates |> List.forall (fun predicate -> predicate x) 

let isBlueCar = combinePredicates [isCar;isBlue] 
+1

O in sintassi senza punti: 'let isBlueCar = (|>) >> flip List.forall predicates' –

+0

@RamonSnir Dove è definito' flip'? –

+0

@GoodNightNerdPride Non penso che sia integrato, devi definirlo tu stesso: 'lascia flip f a b = f b a' –

5
let meetsAll preds = preds |> Seq.fold (fun p q x -> p x && q x) (fun _ -> true) 
// or  let meetsAll preds x = preds |> Seq.forall (fun p -> p x) 

come in

let isEven x = x%2 = 0 
let isDiv5 x = x%5 = 0 
let isDiv7 x = x%7 = 0 

let div257 = meetsAll [isEven; isDiv5; isDiv7] 

for i in 1..100 do 
    if div257 i then 
     printfn "%d" i 

Non v'è alcuna funzione di libreria standard per esso, ma ci sono una pletora di battute si può definire da soli, come dimostrano le risposte qui.