从两个谓词中生成一个谓词(monoid 的工作,折叠?)

Generate a predicate out of two predicates (job for monoid, fold?)

我有两个谓词

interface Foo {}
interface Bar {}
declare const isFoo: (a:unknown):a is Foo
declare const isBar: (a:unknown):a is Bar

组合两个谓词以创建新谓词的功能方法是什么(为简单起见,我们假设它是 a => isFoo(a) && isBar(a)

使用 fp-ts,我最初认为我可以 fold(monoidAll)([isFoo, isBar]),但 fold 期望数组是布尔值,而不是计算结果为布尔值的函数。

这个有效

import { monoid as M, function as F, apply as A, identity as I, reader as R } from 'fp-ts'

interface Foo{}
interface Bar{}

declare const isFoo:(a:unknown) => a is Foo
declare const isBar:(a:unknown) => a is Bar

const isFooAndBar = F.pipe(A.sequenceT(R.reader)(isFoo, isBar), R.map(M.fold(M.monoidAll)))

但是男孩你好就是那么令人费解。我想可能还有另一种方法。我最终写了我自己的幺半群,它接受两个谓词并将它们组合起来,称之为 monoidPredicateAll:

const monoidPredicateAll:M.Monoid<Predicate<unknown>> = {
  empty: ()=>true,
  concat: (x,y) => _ => x(_) && y(_)
}

是否有规范的 FP 方式来组合两个谓词?我知道我可以做类似

的事情
xs.filter(x => isFoo(x) && isBar(x))

但是它可能会因为更多的谓词而变得复杂,并且重新使用幺半群使得我不太可能打错字如 isFoo(x) || isBar(x) && isBaz(x) 当我的意思是所有 && (这就是xs.filter(fold(monoidPredicateAll)(isFoo,isBar,isBaz)) 会帮忙的。

我在 SO 上找到了关于此的讨论,但它是关于 Java 和内置 Predicate 类型的,所以没有直接解决我的问题。

是的,我想多了:)

我最终这样做了:

export const monoidPredicateAll:Monoid<Predicate<unknown>> = {
    empty: ()=>true,
    concat: (x,y) => _ => x(_) && y(_)
}

那我可以

import {monoid as M} from 'fp-ts'
declare const isFoo: Predicate<number>
declare const isBar: Predicate<number>

const isFooAndBar = M.fold(monoidPredicateAll)([isFoo,isBar])

对于其他寻找可行解决方案的人,基于@user1713450 的回答

import * as P from 'fp-ts/lib/Predicate';
import * as M from 'fp-ts/Monoid';

const createMonoidPredicateAll = <T>(): M.Monoid<P.Predicate<T>> => ({
  empty: () => true,
  concat: (x, y) => (_) => x(_) && y(_),
});

export const combine = <T>(predicates: P.Predicate<T>[]) =>
  M.concatAll(createMonoidPredicateAll<T>())(predicates);