2012-06-01 17 views
20

¿Existe una forma estándar de combinar predicados lógicamente en F #? Por ejemplo, digamos que tengo isCar x y isBlue x entonces quiero algo que me da:Combinación de predicados en F #

let isBlueCar x = isCar x && isBlue x 

Pero el uso de algún tipo de composición, en lugar de invocación, tal como:

let isBlueCar x = isCar && isBlue 

Preferentemente, que algo podría aceptar una cantidad grande/arbitraria de predicados.

Respuesta

21

Podría definir un combinador.

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

luego hacer

let isBlueCar = isCar <&> isBlue 
+3

... y realmente es así de fácil, ¿eh? Me encanta F #. – GregRos

+0

@GregRos - echa un vistazo a FParsec (http://www.quanttec.com/fparsec), una biblioteca de análisis maravillosamente elaborada construida utilizando el enfoque de combinadores :-) – theburningmonk

+0

Tengo: P Estoy escribiendo código en este momento:) – GregRos

2

¿Esto es lo que estás buscando?

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

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

> let isBlueCar = isCar &&< isBlue 

val isBlueCar : (int -> bool) 
4

que podría hacer algo como lo siguiente:

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

De manera más general:

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

let isBlueCar = combinePredicates [isCar;isBlue] 
+1

O en sintaxis sin puntos: 'let isBlueCar = (|>) >> flip List.forall predicados' –

+0

@RamonSnir ¿Dónde se define' flip'? –

+0

@GoodNightNerdPride No creo que esté incorporado, debe definirlo usted mismo: 'let 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) 

como en

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 

No hay función de la biblioteca estándar para ella, pero hay una gran cantidad de una sola línea que se pueden definir por su cuenta, como lo demuestran las respuestas aquí.