Typescript 在fp ts中的任意一个上使用GetApplicationValidation后,如何管道ap调用?
昨天,我和几位同事试图获得一个玩具示例,用于fp ts中的应用程序验证。我们最终通过手动将每个中间步骤存储在一个变量中并调用下一个步骤来实现。但是使用fp-ts中的管道函数会更加优雅。使用其中一个直接工作,但不会将多个左值合并为一个(例如,将数组与字符串错误串联)。 但是对于pipe(),ap()调用需要两个参数,但只能得到一个。在这里,我们如何正确使用管道:Typescript 在fp ts中的任意一个上使用GetApplicationValidation后,如何管道ap调用?,typescript,applicative,fp-ts,Typescript,Applicative,Fp Ts,昨天,我和几位同事试图获得一个玩具示例,用于fp ts中的应用程序验证。我们最终通过手动将每个中间步骤存储在一个变量中并调用下一个步骤来实现。但是使用fp-ts中的管道函数会更加优雅。使用其中一个直接工作,但不会将多个左值合并为一个(例如,将数组与字符串错误串联)。 但是对于pipe(),ap()调用需要两个参数,但只能得到一个。在这里,我们如何正确使用管道: import * as E from "fp-ts/lib/Either"; import * as RA from
import * as E from "fp-ts/lib/Either";
import * as RA from "fp-ts/lib/ReadonlyArray";
import { pipe } from "fp-ts/lib/function";
export class CreditCard {
constructor(
public readonly number: string,
public readonly expiry: string,
public readonly cvv: string
) { }
}
export const validate = (
card: CreditCard
): E.Either<ReadonlyArray<string>, CreditCard> => {
const createCreditCard = (a: string) => (b: string) => (c: string) =>
new CreditCard(a, b, c);
const v1 = (s: string): E.Either<ReadonlyArray<string>, string> => {
return s !== "invalid" ? E.right(s) : E.left(RA.of("invalid number"));
};
const v2 = (s: string): E.Either<ReadonlyArray<string>, string> => {
return s !== "invalid" ? E.right(s) : E.left(RA.of("invalid expiry"));
};
const v3 = (s: string): E.Either<ReadonlyArray<string>, string> => {
return s !== "invalid" ? E.right(s) : E.left(RA.of("invalid cvv"));
};
const V = E.getApplicativeValidation((RA.getSemigroup<string>()));
// this does not work, because V.ap wants 2 arguments but only has 1?
// const fromPipe = pipe(
// V.of(createCreditCard),
// V.ap(v1(card.number)),
// V.ap(v2(card.expiry)),
// V.ap(v3(card.cvv))
// );
// return fromPipe;
// this works, but is ugly
const liftedFunction = V.of(createCreditCard);
const afterFirstValidation = V.ap(liftedFunction, v1(card.number));
const afterSecondValidation = V.ap(afterFirstValidation, v2(card.expiry));
const afterThirdValidation = V.ap(afterSecondValidation, v3(card.cvv));
return afterThirdValidation;
};
import*作为E从“fp ts/lib/earth”导入;
从“fp ts/lib/ReadonlyArray”导入*作为RA;
从“fp ts/lib/function”导入{pipe};
出口信用卡{
建造师(
公共只读编号:string,
公共只读到期日:字符串,
公共只读cvv:字符串
) { }
}
导出常量验证=(
信用卡:信用卡
):E.任一=>{
const createCreditCard=(a:string)=>(b:string)=>(c:string)=>
新信用卡(a、b、c);
常量v1=(s:string):E.其中一个=>{
返回s!==“无效”?E.右:E.左(RA.of(“无效数字”);
};
常量v2=(s:string):E.或=>{
返回s!=“无效”?E.右侧:E.左侧(相对有效(“无效到期”);
};
constv3=(s:string):E{
返回s!==“无效”?E.右:E.左(RA.of(“无效cvv”);
};
const V=E.getApplicationValidation((RA.getSemigroup());
//这不起作用,因为V.ap需要2个参数,但只有1个?
//const fromPipe=管道(
//V.of(创建信用卡),
//V.ap(v1(卡号)),
//V.ap(v2(卡到期)),
//增值税(v3(信用卡增值税))
// );
//从管道返回;
//这是可行的,但很难看
const liftedFunction=V.of(createCreditCard);
const afterFirstValidation=V.ap(提升函数,v1(卡号));
const afterSecondValidation=V.ap(首次验证后,v2(卡到期));
const afterThirdValidation=V.ap(afterSecondValidation,v3(card.cvv));
第三次验证后返回;
};
或者。GetApplicationValidation
返回具有类方法的不可管道版本的Application2C
的实例。当前,获取使用combinators计算的实例的可管道版本的方法(如GetApplicationValidation
)是将实例从pipeable.ts
模块传递到pipeable
combinator
因此,请将代码更改为:
const validation = E.getApplicativeValidation(RA.getSemigroup<string>())
const V = pipeable(validation)
const fromPipe = pipe(
validation.of(createCreditCard),
V.ap(v1(card.number)),
V.ap(v2(card.expiry)),
V.ap(v3(card.cvv))
)
const validation=E.getApplicationValidation(RA.getSemigroup())
常数V=管道(验证)
const fromPipe=管道(
验证(createCreditCard),
V.ap(v1(卡号)),
V.ap(v2(卡到期)),
增值税(v3(信用卡增值税))
)
你会发现它能按你的意愿工作
然而,我相信在fp ts
v3.x.x中,类型类接口将在默认情况下更改为所有可管道接口,因此pipeable
的需求将消失