22

Is there a standard way of logically combining predicates in F#? For example, let's say I have isCar x and isBlue x then I want something that gives me:

let isBlueCar x = isCar x && isBlue x

But using some sort of composition, rather than invocation, maybe like:

let isBlueCar x = isCar && isBlue

Preferably, that something would be able to accept a large/arbitrary number of predicates.

GregRos
  • 8,667
  • 3
  • 37
  • 63

4 Answers4

27

You could define a combinator.

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

then do

let isBlueCar = isCar <&> isBlue
Daniel
  • 47,404
  • 11
  • 101
  • 179
7
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)

as 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

There is no standard library function for it, but there are a plethora of one-liners you can define on your own, as evidenced by the answers here.

Brian
  • 117,631
  • 17
  • 236
  • 300
5

You could do something like the following:

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

More generally:

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

let isBlueCar = combinePredicates [isCar;isBlue]
Stephen Swensen
  • 22,107
  • 9
  • 81
  • 136
2

Is this what you're looking for?

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

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

> let isBlueCar = isCar &&< isBlue

val isBlueCar : (int -> bool)
Ramon Snir
  • 7,520
  • 3
  • 43
  • 61