[英]Merging typed structs with FP-TS
When using FP-TS I often end up with structs being inside a Task
or an IO
.使用 FP-TS 时,我经常会在
Task
或IO中IO
。 I managed to solve the problem by writing a merge function and separate lift functions that make it work with Task
or IO
.我设法通过编写合并 function 和单独的提升功能来解决问题,使其与
Task
或IO
。 See the included code example for a more detailed explanation.有关更详细的说明,请参阅包含的代码示例。 The code works but I'm wondering if the custom functions I wrote are already available in FP-TS in some shape or form.
该代码有效,但我想知道我编写的自定义函数是否已经以某种形式或形式在 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)
Merging structs of the same type can be achieved with a Monoid
instance (see getStructMonoid
), but you're looking to merge structs with different interfaces, and there's not a type class for that operation.可以使用
Monoid
实例来合并相同类型的结构(请参阅getStructMonoid
),但是您希望合并具有不同接口的结构,并且该操作没有 class 类型。 However, Object.assign
is equivalent to your merge
function, except that it can merge up to four arguments (any more than that and you'll get an any
in TypeScript).但是,
Object.assign
等效于您的merge
function,除了它最多可以合并四个 arguments(除此之外,您将在 TypeScript 中得到一个any
)。
As for ioLift
, there's nothing equivalent to that in fp-ts
, but your implementation of sequenceT
+ map
is the standard way of applying a function to some arguments when they each happen to be wrapped in some applicative functor, standard for fp-ts
, that is, given the limitations of TypeScript (see @gcanti's comment here about why there's not liftN
function). As for
ioLift
, there's nothing equivalent to that in fp-ts
, but your implementation of sequenceT
+ map
is the standard way of applying a function to some arguments when they each happen to be wrapped in some applicative functor, standard for fp-ts
,也就是说,鉴于 TypeScript 的局限性(请参阅@gcanti 的评论,了解为什么没有liftN
功能)。
Given how trivial the sequenceT
+ map
composition is, one could argue that it doesn't meet the Fairbairn Threshold , meaning it's easier to just combine sequenceT
+ map
inline whenever you find yourself in this situation rather than writing a specialized utility liftWhatever
for every applicative functor you come across.考虑到
sequenceT
+ map
组合是多么微不足道,有人可能会争辩说它不符合Fairbairn Threshold ,这意味着只要你发现自己处于这种情况,将sequenceT
+ map
内联更容易,而不是为每个应用程序编写一个专门的实用程序liftWhatever
你遇到的函子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.