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