2012-06-01 12 views
20

Gibt es eine Standardmethode zum logischen Kombinieren von Prädikaten in F #? Zum Beispiel lassen Sie uns sagen, ich habe isCar x und isBlue x dann etwas, das ich will, das gibt mir:Kombinieren von Prädikaten in F #

let isBlueCar x = isCar x && isBlue x 

Aber irgendeine Art von Zusammensetzung, anstatt Aufruf, vielleicht wie:

let isBlueCar x = isCar && isBlue 

Vorzugsweise dass etwas wäre in der Lage, eine große/willkürliche Anzahl von Prädikaten zu akzeptieren.

Antwort

21

Sie könnten einen Kombinator definieren.

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

dann tun

let isBlueCar = isCar <&> isBlue 
+3

... und es ist wirklich so einfach, nicht wahr? Ich liebe F #. – GregRos

+0

@GregRos - schau dir FParsec (http://www.quanttec.com/fparsec) an, eine wunderschön gestaltete Parsing-Bibliothek, die mit dem Kombinator-Ansatz erstellt wurde :-) – theburningmonk

+0

Ich habe: P Ich schreibe Code darauf, wie wir sprechen:) – GregRos

2

Ist das wonach Sie suchen?

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

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

> let isBlueCar = isCar &&< isBlue 

val isBlueCar : (int -> bool) 
4

Sie so etwas wie das folgende tun könnte:

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

Allgemeiner:

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

let isBlueCar = combinePredicates [isCar;isBlue] 
+1

Oder in Punkt-freie Syntax: 'Lassen Sie isBlueCar = (|>) >> Flip-Liste.forall Prädikate' –

+0

@RamonSnir Wo ist' Flip' definiert obwohl? –

+0

@GoodNightNerdPride Ich glaube nicht, dass es eingebaut ist, Sie müssen es selbst definieren: 'Lassen Sie 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) 

wie 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 

Es gibt keine Standard-Library-Funktion für sie, aber es gibt eine Fülle von Einzeiler Sie selbst definieren können, wie hier durch die Antworten belegt.