在 fp-ts 中,我试图将一些可能失败的异步任务链接在一起,TaskEither
但我需要稍后在链中使用中间任务的结果。
在这个例子中:
const getFoo = (a: string): Promise<Foo> => {};
const getBar = (foo: Foo): Promise<Bar> => {};
const mkFooBar = (foo: Foo, bar: Bar): Promise<FooBar> => {};
const async main1: Promise<FooBar> => {
const a = "a";
const foo = await getFoo(a);
const bar = await getBar(foo);
const fooBar = await mkFooBar(foo, bar);
return Promise.resolve(fooBar);
};
const main2: Promise<FooBar> => {
const a = "a";
return pipe(
TE.tryCatch(() => getFoo(a), e => e),
TE.chain(foo => …
Run Code Online (Sandbox Code Playgroud) 我仍在学习和使用 fp-ts 并且无法弄清楚这一点。
我有一个数组,Either<any, number>[]
我想得到一个Either<any, number[]>
.
我已经查看Apply.sequenceT
了示例 sequenceToOption,它看起来很接近。
import { NumberFromString } from 'io-ts-types/lib/NumberFromString'
import { Either } from 'fp-ts/lib/Either'
const a:Either<any,number>[] = ['1','2','3'].map(NumberFromString.decode)
console.log(a)
// [ { _tag: 'Right', right: 1 },
// { _tag: 'Right', right: 2 },
// { _tag: 'Right', right: 3 } ]
Run Code Online (Sandbox Code Playgroud)
我想要一个错误或数字数组。
我的目标是从 API 请求交易并将其存储到数据库中。响应是分页的,我想读取每一页并批量存储交易。
因此,对于一个请求/响应周期,我希望在获取下一批之前处理结果并将其存储到数据库中。
我如何在 fp-ts 中以惯用的方式执行此操作?我注入实际的 HTTP 获取调用,(url:string, init:RequestInit) => TE.TaskEither<Error, Response>
以保持其可测试性。
到目前为止,我已经测试了 RxJS 和 fp-ts,即使我让它工作也有点复杂。
确实尝试了递归函数和生成器,但我没有成功地对其进行延迟评估。
是否有任何现有的 fp-ts 示例显示了一个延迟评估的流,其中每个元素都依赖于前一个元素?
我是 fp-ts 新手。在处理组合 Either、IO 和 ... 时,我习惯使用 scala 进行理解。问题是,假设我们有带签名的函数
either(T): Either<Error, T>
ioEither(T): IOEither<Error, T>
taskEither(T): TaskEither<Error, T>
...
Run Code Online (Sandbox Code Playgroud)
我想把它们结合起来,我得到了一些类似的东西
pipe(T, taskEither, map(either)): TaskEither<Error, Either<Error, T>>
Run Code Online (Sandbox Code Playgroud)
哪个应该被压平。
如何组合T -> M<T>
其中 M 是 IO 或 Task,以及T -> M<Error, T>
M 是 Either、TaskEither 或 IOEither 的类型的函数,在过程中进行扁平化,就像使用 scala 进行理解一样?
我是 FP-TS 的新手,仍然不太明白如何使用TaskEither
. 我正在尝试异步读取文件,然后使用 yaml-parse-promise 解析结果字符串。
==编辑==
我使用文件的完整内容更新了代码以提供更多上下文,并应用了 MnZrK 提供的一些建议。抱歉,我对 FP-TS 还很陌生,并且仍在努力使类型匹配。
现在我的错误在于该行map(printConfig)
:
Argument of type '<E>(fa: TaskEither<E, AppConfig>) => TaskEither<E, AppConfig>' is not assignable to parameter of type '(a: TaskEither<unknown, AppConfig>) => Either<unknown, Task<any>>'.
Type 'TaskEither<unknown, AppConfig>' is not assignable to type 'Either<unknown, Task<any>>'.
Type 'TaskEither<unknown, AppConfig>' is missing the following properties from type 'Right<Task<any>>': _tag, rightts(2345)
Run Code Online (Sandbox Code Playgroud)
[我通过使用 TaskEither 中的 getOrElse 解决了这个问题,而不是来自 Either 库]
==编辑结束==
我已使用 IOEither 成功执行此操作,作为此项目的同步操作: https: //github.com/anotherhale/fp-ts_sync-example。
我还查看了这里的示例代码: https ://gcanti.github.io/fp-ts/recipes/async.html
完整代码在这里: …
我想以某种方式将 Fetch API 包装在 fp-ts 中:
import * as TE from 'fp-ts/lib/TaskEither';
import * as E from 'fp-ts/lib/Either';
import { flow } from 'fp-ts/lib/function';
import { pipe } from 'fp-ts/lib/pipeable';
const safeGet = (url: string): TE.TaskEither<Error, Response> => TE.tryCatch(
() => fetch(url),
(reason) => new Error(String(reason))
);
const processResponce = flow(
(x: Response): E.Either<Error, Response> => {
return x.status === 200
? E.right(x)
: E.left(Error(x.statusText))
},
TE.fromEither
);
export const httpGet = (url: string): …
Run Code Online (Sandbox Code Playgroud) 我有一个字符串列表,string[]
我映射了一个返回的验证函数Either<Error, string>[]
我想要[Error[], string[]]
所有验证错误和所有经过验证的字符串。
可以sequence(Either.Applicative)
或traverse(Either.Applicative)
返回遇到的所有错误吗?我只收到Either<Error, string[]>
,只是返回第一个错误。我是否需要编写自己的应用程序,带有合并左右半群的东西?
我可以通过更改为来获得所有map
错误。reduce
fold
我还考虑反转验证,并运行两次。一个函数返回有效字符串,一个函数返回错误。
我在尝试使用 FP-TS 实现事物时不断遇到的一种模式是,当我的管道涉及到 TaskEither 的分支和合并分支时。
合并似乎工作得很好,因为我可以使用sequenceT创建数组并将它们通过管道传输到函数中,然后使用所有这些值。
似乎不太有效的是更复杂的依赖关系图,其中一个函数需要较早的项目,然后需要该函数的输出以及第一个任务的原始结果。
基本上像这样的函数签名(这可能不是 100% 正确的类型,但了解其要点):
function fetchDataA(): TaskEither<Error, TypeA> {
}
function fetchBBasedOnOutputOfA(a: TypeA): TaskEither<Error, TypeB> {
}
function fetchCBasedOnOutputOfAandB(a: TypeA, b: TypeB): TaskEither<Error, TypeC> {
}
Run Code Online (Sandbox Code Playgroud)
因为在管道中,你可以很好地为前两个作曲
pipe(
fetchDataA(),
TE.map(fetchBBasedOnOutputOfA)
)
Run Code Online (Sandbox Code Playgroud)
这个管道按预期返回 TaskEither<Error, TypeB> ,并且地图处理错误对我来说很好。
而要执行最后一个操作,我现在需要输入 TypeA 作为参数,但它不可用,因为它已传递到 B 中。
一种解决方案是让函数 B 同时输出 A 和 B,但这感觉不对,因为创建 B 的函数不必知道其他某个函数也需要 A。
另一种方法是创建某种中间函数来存储 A 的值,但在我看来,这破坏了使用 TaskEither 的全部意义,即我要抽象出所有错误类型并自动处理它。
我会有某种奇怪的功能:
async function buildC(a : TypeA): TaskEither<Error, TypeC> {
const b = await fetchBBasedOnOutputOfA(a);
// NOW DO MY OWN ERROR …
Run Code Online (Sandbox Code Playgroud) 我正在尝试创建以下的 io-ts 接口
我的接口.ts
export interface myInterface {
[key:string]?: string | undefined | null
}
Run Code Online (Sandbox Code Playgroud)
我想把它变成 io-ts 等价物。最终目标是将它与另一个现有的 io-ts 接口结合起来
我的其他interface.ts
export const MyOtherInterfaceV = t.interface({
requiredProp1: ValidString// custom type, checks string is populated
requiredProp2: ValidString
// All other fields marked as required
})
export type MyOtherInterface = t.TypeOf<typeof MyOtherInterfaceV>;
Run Code Online (Sandbox Code Playgroud)
这个想法是我需要一个类型来表示一个有效载荷,它有一些我们需要并且必须有效的字段,还有一些我们不知道并且可以是可选的。我们希望将这些组合起来以供稍后处理使用,最终存储在 dynamodb 中
当没有一个函数是异步的时,我有以下程序可以正常工作。
interface Product {
count: number
pricePerItem: number
}
interface Tax {
tax: number
}
interface Delivery {
delivery: number
}
interface PTD { //ProductTaxDelivery
p: Product
t: number
d: number
}
function getProduct(): Either<Error, Product> {
return E.right({ count: 10, pricePerItem: 5 })
}
function getTax(p: Product): Either<Error, number> {
return E.right(p.pricePerItem * p.count * 0.085)
}
function getDelivery(p: Product): Either<Error, number> {
return E.right(p.count * 0.05)
//or maybe return E.left(Error('some error in delivery happened'))
}
function run(): Either<Error, …
Run Code Online (Sandbox Code Playgroud)