0

I want to use Option instead of switch. I tried Alt.altAll, and it works fine:

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'),
  ])
}

But it always evaluates the whole Option array instead of short-circuiting, so I want to know if there is a way to implement logic like below? Thanks!

// 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'),
  ])
}
Lauren Yim
  • 12,700
  • 2
  • 32
  • 59
Mxcpanel
  • 95
  • 7

1 Answers1

0

If you are wanting to implement a function similar to an existing one, it can be helpful to look at the source code for e.g. altAll. Modifying that slightly:

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)
}

If you’re only using it for Option, you only need the <F extends URIS>(F: Alt1<F>) overload. The other overloads are for types such as Either which have more than 1 type argument.

This works because F.alt already supports having a lazy second argument, so you can do O.Alt.alt(O.none, () => O.some(1)) for example.

Lauren Yim
  • 12,700
  • 2
  • 32
  • 59