如何以无点风格实现fp-ts中O.alt的等效功能?
用无点风格实现fp-ts Option的备选取值逻辑
你需要将一个值传入两个返回Option类型的函数,取第一个返回Some的结果,当前用O.alt的写法需要显式传递参数,希望改成无点风格的写法。原核心逻辑如下:
O.chain<URLSearchParams, string>((p) => pipe( getFromNormal(p), O.alt(() => getFromOther(p)) ) ),
你尝试用O.chain(O.alt(getFromNormal, getFromOther))的无点形式,但O.alt不支持直接接收两个函数作为参数,以下是可行的解决方案:
方案1:封装辅助函数实现纯无点风格
由于O.alt的签名是(that: Lazy<Option<A>>) => (fa: Option<A>) => Option<A>,它接收延迟执行的备选Option而非直接接收函数。我们可以封装一个辅助函数,把两个接收相同参数、返回Option的函数组合成一个新函数,内部自动用O.alt处理结果:
import { constFalse, pipe } from "fp-ts/function"; import * as O from "fp-ts/Option"; const normalParams = new URLSearchParams("normal=yes"); const otherParams = new URLSearchParams("otherNormal=yes"); const getFromNormal = (params: URLSearchParams): O.Option<string> => O.fromNullable(params.get("normal")); const getFromOther = (params: URLSearchParams): O.Option<string> => O.fromNullable(params.get("otherNormal")); // 封装辅助函数:组合两个返回Option的函数,取第一个Some结果 const altFn = <A, B>(f: (a: A) => O.Option<B>, g: (a: A) => O.Option<B>) => (a: A) => pipe(f(a), O.alt(() => g(a))); // 修改为无点风格的核心逻辑 const isNormal = (params?: URLSearchParams): boolean => pipe( params, O.fromNullable, O.chain(altFn(getFromNormal, getFromOther)), O.map((s) => s === "yes"), O.getOrElse(constFalse) ); // 验证逻辑正确性 console.assert(isNormal(normalParams) === true); console.assert(isNormal(otherParams) === true); console.assert(isNormal(undefined) === false);
这样O.chain的参数就变成了纯无点风格的altFn(getFromNormal, getFromOther),完全符合你的需求。
方案2:用flow简化近似无点写法
如果你不想额外封装函数,也可以用flow串联逻辑,通过隐式传递参数实现近似无点的风格:
// 核心逻辑修改为flow形式 const isNormal = (params?: URLSearchParams): boolean => pipe( params, O.fromNullable, O.chain(flow( getFromNormal, O.alt(() => getFromOther) )), O.map((s) => s === "yes"), O.getOrElse(constFalse) );
这里O.alt的回调会自动接收当前上下文的参数p,写法简洁且接近无点风格。
内容的提问来源于stack exchange,提问作者I Stevenson
相关产品推荐
相关产品推荐

