从两个谓词中生成一个谓词(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)))

但是男孩霍迪是那么的复杂。我想还有别的办法。我最终编写了自己的monoid,它接受两个谓词并将它们组合在一起,称之为monoidPredicateAll:

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

有没有一种规范的FP方式来组合两个谓词?我知道我可以做一些类似的事情

xs.filter(x => isFoo(x) && isBar(x))

但是,如果有更多的谓词,它可能会变得复杂,并且重新使用monoid会使我不太可能在指所有&&时犯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);

相关内容

  • 没有找到相关文章

最新更新