typescript 如何实现lazy altAll方法?

yr9zkbsy  于 2023-02-05  发布在  TypeScript
关注(0)|答案(1)|浏览(117)

我想用Option代替Switch,我试过Alt.altAll,效果很好:

function foo(a: number) {
  return alt.altAll(O.Alt)<string>(O.none)([
    O.fromPredicate(() => a >= 85)('A'),
    O.fromPredicate(() => a >= 75)('B'),
    O.fromPredicate(() => a >= 75)('C'),
    O.some('D'),
  ])
}

但是它总是计算整个Option数组,而不是 short-circuiting,所以我想知道是否有一种方法可以实现下面这样的逻辑?谢谢!

// I don't want to use Option.alt because that would add one more level of nesting.
function foo(a: number) {
  return alt.lazyAltAll(O.Alt)<string>(O.none)([
    () => O.fromPredicate(() => a >= 85)('A'),
    () => O.fromPredicate(() => a >= 75)('B'),
    () => O.fromPredicate(() => a >= 75)('C'),
    () => O.some('D'),
  ])
}
rsaldnfx

rsaldnfx1#

如果你想实现一个类似于现有函数的函数,查看源代码会很有帮助,例如altAll

import type {Alt, Alt1, Alt2, Alt2C, Alt3, Alt3C, Alt4} from 'fp-ts/Alt'
import type {HKT, Kind, Kind2, Kind3, Kind4, URIS, URIS2, URIS3, URIS4} from 'fp-ts/HKT'
import type {Lazy} from 'fp-ts/function'
// type Lazy<A> = () => A 

function lazyAltAll<F extends URIS4>(F: Alt4<F>): <S, R, E, A>(startWith: Kind4<F, S, R, E, A>) => (as: readonly Lazy<Kind4<F, S, R, E, A>>[]) => Kind4<F, S, R, E, A>
function lazyAltAll<F extends URIS3>(F: Alt3<F>): <R, E, A>(startWith: Kind3<F, R, E, A>) => (as: readonly Lazy<Kind3<F, R, E, A>>[]) => Kind3<F, R, E, A>
function lazyAltAll<F extends URIS3, E>(F: Alt3C<F, E>): <R, A>(startWith: Kind3<F, R, E, A>) => (as: readonly Lazy<Kind3<F, R, E, A>>[]) => Kind3<F, R, E, A>
function lazyAltAll<F extends URIS2>(F: Alt2<F>): <E, A>(startWith: Kind2<F, E, A>) => (as: readonly Lazy<Kind2<F, E, A>>[]) => Kind2<F, E, A>
function lazyAltAll<F extends URIS2, E>(F: Alt2C<F, E>): <A>(startWith: Kind2<F, E, A>) => (as: readonly Lazy<Kind2<F, E, A>>[]) => Kind2<F, E, A>
function lazyAltAll<F extends URIS>(F: Alt1<F>): <A>(startWith: Kind<F, A>) => (as: readonly Lazy<Kind<F, A>>[]) => Kind<F, A>
function lazyAltAll<F>(F: Alt<F>): <A>(startWith: HKT<F, A>) => (as: readonly Lazy<HKT<F, A>>[]) => HKT<F, A>
function lazyAltAll<F>(F: Alt<F>): <A>(startWith: HKT<F, A>) => (as: readonly Lazy<HKT<F, A>>[]) => HKT<F, A> {
  return startWith => as => as.reduce(F.alt, startWith)
}

如果你只在Option上使用它,你只需要<F extends URIS>(F: Alt1<F>)重载。其他重载是针对Either这样的类型的,它有一个以上的类型参数。
这样做是因为F.alt已经支持lazy second参数,所以可以使用O.Alt.alt(O.none, () => O.some(1))作为例子。

相关问题