【问题标题】:Merging typed structs with FP-TS将类型化结构与 FP-TS 合并
【发布时间】:2021-01-02 13:38:22
【问题描述】:

在使用 FP-TS 时,我经常会发现 structsTaskIO 中。我设法通过编写合并函数和单独的提升函数来解决问题,使其与TaskIO 一起工作。有关更详细的说明,请参阅包含的代码示例。该代码有效,但我想知道我编写的自定义函数是否已经以某种形式或形式在 FP-TS 中可用。

import { deepStrictEqual as assertEqual } from 'assert'
import { IO, of, io, map } from 'fp-ts/lib/IO';
import { sequenceT } from 'fp-ts/lib/Apply';
import { pipe, tupled } from 'fp-ts/lib/function';

type Merge<A, B> = A & B
function merge<A, B>(a: A, b: B): Merge<A, B> {
  return {...a, ...b}
}

type Foo = { foo: 123 }
type Bar = { bar: 456 }
type FooBar = Merge<Foo, Bar>;

const foo: Foo = { foo: 123 }
const bar: Bar = { bar: 456 }
const fooBar: FooBar = merge(foo, bar)

type IOLift<A, AS extends Array<any>, B> = (a: IO<A>, ...as: { [I in keyof AS]: IO<AS[I]> }) => IO<B> 
function ioLift<A, AS extends Array<any>, B>(f: (a: A, ...as: AS) => B): IOLift<A, AS, B> {
  return (...a) => pipe(
    sequenceT(io)(...a),
    map(tupled(f))
  )
}

const ioMerge = ioLift(merge)

const ioFoo: IO<Foo> = of(foo)
const ioBar: IO<Bar> = of(bar)
const ioFooBar: IO<FooBar> = ioMerge(ioFoo, ioBar)

assertEqual(ioFooBar(), fooBar)

【问题讨论】:

    标签: typescript fp-ts


    【解决方案1】:

    可以使用Monoid 实例(请参阅getStructMonoid)来合并相同类型的结构,但是您希望合并具有不同接口的结构,并且该操作没有类型类。但是,Object.assign 等价于您的 merge 函数,只是它最多可以合并四个参数(除此之外,您将在 TypeScript 中获得一个 any)。

    至于ioLift,在fp-ts 中没有什么等价的,但是您对sequenceT + map 的实现是将函数应用于某些参数的标准方法,当它们每个都包含在某些参数中时applicative functor,fp-ts 的标准,也就是说,鉴于 TypeScript 的局限性(请参阅@gcanti 的评论 here,了解为什么没有 liftN 函数)。

    考虑到sequenceT + map 组合是多么微不足道,有人可能会争辩说它不符合Fairbairn Threshold,这意味着只要你发现自己在这种情况,而不是为遇到的每个应用函子编写专门的实用程序 liftWhatever

    【讨论】:

      猜你喜欢
      • 2022-01-07
      • 2021-12-04
      • 1970-01-01
      • 2018-06-22
      • 2021-05-26
      • 2020-08-16
      • 2021-07-17
      • 1970-01-01
      • 2018-01-24
      相关资源
      最近更新 更多