【发布时间】:2021-03-14 16:44:55
【问题描述】:
有没有办法将 IOEither 和 TaskEither 表示为单个 Monad,其中还包括 tryCatch?
我目前将通过 HTTP 使用 API,因此使用 TaskEither 是有意义的,但预计此代码将“离家更近”迁移,此时将其设为 IOEither 是有意义的。所以我想写一个无标签风格的消费者界面
interface EngineRepository<M extends URIS2> {
calculateNumber: (i:SomeData) => Kind2<M, DomainError, number>
}
const getRepo = <M>(m:M extends URIS2):EngineRepository<M> => ({
calculateNumber: someCalculation(m)()
})
const calculateNumber = <M>(m:M extends URIS2) => flow(/* M.chain, M.map, etc. works great! */)
到目前为止一切顺利!但是,虽然 Option、Either、TaskEither、IOEither 等有一个 tryCatch,但我可以说它不是任何接口的一部分。所以我正在尝试创建自己的:
interface Tryable<M extends URIS2> extends Monad2<M> {
tryCatch: <E,A>(f:Lazy<A>, onError: (reason:unknown) => E) => Kind2<M, E, A>
}
const calculateNumber = <M>(m:M extends URIS2) =>
flow(/* M.tryCatch works great now! */)
这里的问题是IOError 是同步的,所以f:Lazy<A> 很好,TaskEither 是异步的,所以它需要改为f:Lazy<Promise<A>>。
有没有更好的方法来解决这个问题,或者这是不可能的?我是否需要始终使用 TaskEither,然后添加一个将 IOEither 转换为 TaskEither 并放弃无标记 final 的步骤?
【问题讨论】:
-
“离家更近”意味着目前我正在使用一个不同 Java 微服务的 API(所以它几乎不是“微”哈哈!),但我认为另一个团队正在将它移植到 TypeScript 和将它添加到这个应用程序的代码库中,所以
IOEither。 -
fp-ts - async/sync中
Task和IO有什么区别? -
@scriptum 是的。
interface Task<A> { ():Promise<A> }和interface IO<A> { ():A } -
(以及扩展名
TaskEither<E,A> { ():Promise<Either<E,A>> }和IOEither<E,A> { ():Either<E,A> }) -
我不知道 fp-ts,但是一个更通用的 monad 可以处理异步(任务)和延迟/延迟同步(IO)计算并具有副作用是 continuation monad,巧合的是,它也是一个 monad变压器,因此您可以将其与您选择的异常处理机械地结合起来。
标签: typescript functional-programming fp-ts tagless-final