在F#中合并谓词

23

在 F# 中,是否有一种标准的逻辑组合谓词的方法? 例如,假设我有 isCar xisBlue x,我想要得到某个东西:

let isBlueCar x = isCar x && isBlue x

但是使用一种组合而不是调用的方式,可能像这样:

let isBlueCar x = isCar && isBlue

最好是这个东西能够接受大量或任意数量的谓词。

4个回答

28
你可以定义一个组合子。
let (<&>) f g = (fun x -> f x && g x)
然后执行
let isBlueCar = isCar <&> isBlue

4
那真的很简单,是吗?我喜欢 F#。 - GregRos
@GregRos - 请查看 FParsec(http://www.quanttec.com/fparsec),这是一个使用组合子方法构建的精美解析库 :-) - theburningmonk

8
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)

就像

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

没有标准库函数可以实现此功能,但是您可以自己定义许多一行代码的函数,这些答案已经证明了这一点。


6
您可以采取以下操作:

您可以像以下示例一样进行操作:

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

更一般地说:
let combinePredicates predicates =
    fun x -> predicates |> List.forall (fun predicate -> predicate x)

let isBlueCar = combinePredicates [isCar;isBlue]

1
或者使用点无关语法:let isBlueCar = (|>) >> flip List.forall predicates - Ramon Snir
@RamonSnir flip 定义在哪里? - Good Night Nerd Pride
@GoodNightNerdPride 我认为它不是内置的,你需要自己定义:let flip f a b = f b a - Ramon Snir

3

这是你想要的吗?

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

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

> let isBlueCar = isCar &&< isBlue

val isBlueCar : (int -> bool)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接