【问题标题】:How to go from ReaderEither<R, E, A>[] to ReaderEither<R, E[], A[]> in fp-ts?如何在 fp-ts 中从 ReaderEither<R, E, A>[] 到 ReaderEither<R, E[], A[]>?
【发布时间】:2023-03-29 03:17:01
【问题描述】:

在 fp-ts 中,我如何从 ReaderEither&lt;R, E, A&gt;[] 转到 ReaderEither&lt;R, E[], A[]&gt;?本质上,我想将一组 ReaderEither 实例转换为单个 ReaderEither 实例。

我曾尝试寻找答案,但运气不佳。我是函数式编程和 fp-ts 的新手,所以我仍在尝试围绕所有概念并将它们付诸实践。感谢您的帮助。

【问题讨论】:

  • 我相信 Traversable 可能是关键。我找到了一些将它与 Option 和 Either 一起使用的示例,但我无法让它与 ReaderEither 一起使用。 gcanti.github.io/fp-ts/modules/Traversable.ts.html
  • 您可以从ReaderEither&lt;R, E, A&gt;[]sequenceT 获得ReaderEither&lt;R, E, A[]&gt;,但我不确定如何累积错误。
  • 您确定要ReaderEither&lt;R, E[], A[]&gt; 吗?这与Reader&lt;R, Either&lt;E[], A[]&gt;&gt; 相同;你想要Reader&lt;R, Either&lt;E, A&gt;[]&gt; 吗?
  • 是的,我希望将结果累积到一个Either,而不是多个Either
  • 您希望它如何工作?如果一些ReaderEithers 返回一个Left 而一些返回一个Right 怎么办?您是否希望最终的 Either 依赖于第一个 ReaderEither(例如,如果第一个 ReaderEither 返回一个 Left,则通过累积另一个 Lefts 来返回一个 Left&lt;E[]&gt; 并丢弃 Right s)?如果ReaderEither&lt;R, E, A&gt;[] 为空怎么办?

标签: typescript functional-programming fp-ts


【解决方案1】:

试试这个:

import * as A from 'fp-ts/Array'
import {left, right} from 'fp-ts/Either'
import * as R from 'fp-ts/Reader'
import {flow} from 'fp-ts/function'
import type {ReaderEither} from 'fp-ts/ReaderEither'

const sequenceRE: <R, E, A>(
  fs: ReaderEither<R, E, A>[]
) => ReaderEither<R, E[], A[]> = flow(
  // ReaderEither<R, E, A>[] -> Reader<R, Either<E, A>[]>
  A.sequence(R.reader),
  // Maps the reader: Reader<R, Either<E, A>[]> -> ReaderEither<R, E[], A[]>
  R.map(flow(
    // Either<E, A>[] -> Separated<E[], A[]>
    A.separate,
    // Separated<E[], A[]> -> Either<E[], A[]>
    s => s.left.length ? left(s.left) : right(s.right)
  ))
)

// Right [4, 6]
sequenceRE([r => right(r * 2), r => right(r * 3)])(2)
// Left ['foo', 'bar']
sequenceRE([r => right(r * 2), r => left('foo'), r => left('bar')])(2)
// Right []
sequenceRE([])(2)

代码是这样做的:

  • sequences(从Traversable)将ReaderEither&lt;R, E, A&gt;[]变成Reader&lt;R, Either&lt;E, A&gt;[]&gt;

  • separates(来自CompactableEither&lt;E, A&gt;[]从读者变成{left: E[], right: A[]}

    interface Separated<A, B> {
      readonly left: A
      readonly right: B
    }
    
    // For Array:
    declare const separate: <A, B>(fa: Either<A, B>[]) => Separated<A[], B[]>
    
  • 如果有任何Lefts,则返回带有Left 值的Left,否则返回带有Right 值的Right

【讨论】:

  • 效果很好。非常感谢。这几天我一直在“旋转轮胎”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-19
  • 2017-12-05
  • 2021-11-10
  • 1970-01-01
相关资源
最近更新 更多