Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add liftEither for ObservableEither #39

Open
anthonyjoeseph opened this issue Dec 2, 2020 · 3 comments · May be fixed by #52
Open

Add liftEither for ObservableEither #39

anthonyjoeseph opened this issue Dec 2, 2020 · 3 comments · May be fixed by #52

Comments

@anthonyjoeseph
Copy link
Contributor

anthonyjoeseph commented Dec 2, 2020

I often end up needing a way to use OperatorFunction's on the right case of ObservableEither's

E.g. filter or takeUntil for ObservableEither. Most operators, really

const liftEither = <E, A, B>(
  f: (a: r.Observable<A>) => r.Observable<B>
): ((a: OBE.ObservableEither<E, A>) => OBE.ObservableEither<E, B>) =>
  flow(OB.separate, ({left, right}) =>
    r.merge(pipe(left, ro.map(E.left)), pipe(right, f, ro.map(E.right)))
  )

I can make a P.R. if desired, but I'm not sure if this is the best way to do this.

@anthonyjoeseph
Copy link
Contributor Author

anthonyjoeseph commented Dec 2, 2020

Here's a simple example usage

import {pipe} from 'fp-ts/pipeable'
import * as r from 'rxjs'
import * as E from 'fp-ts/Either'
import * as OB from 'fp-ts-rxjs/lib/Observable'
import * as OBE from 'fp-ts-rxjs/lib/ObservableEither'

const isOdd = (a: number): boolean => a % 2 !== 0

const fa: OBE.ObservableEither<never, number> = pipe(
  r.from([1, 2, 3]),
  OBE.rightObservable
)
const fb: OBE.ObservableEither<never, number> = pipe(
  fa,
  liftEither(OB.filter(isOdd))
)
// fb will emit E.right(1), E.right(3)

(edit: a bit more terse)

@anthonyjoeseph
Copy link
Contributor Author

anthonyjoeseph commented Dec 17, 2020

Just a note - this solution is not ideal, because the input observable is subscribed to twice due to the r.merge call. The redundant emissions are filtered out, but it can make debugging difficult

@anthonyjoeseph
Copy link
Contributor Author

anthonyjoeseph commented Dec 22, 2020

Here's a solution without redundant subscriptions:

export const liftEither = <Err, A, B>(
  f: (a: r.Observable<A>) => r.Observable<B>
) => (obs: OBE.ObservableEither<Err, A>): OBE.ObservableEither<Err, B> => {
  const subjA = new r.Subject<A>()
  const subjB = new r.Subject<Err>()
  obs.subscribe(
    E.fold<Err, A, void>(
      (err) => subjB.next(err),
      (val) => subjA.next(val)
    )
  )
  return r.merge(pipe(subjA, f, OB.map(E.right)), pipe(subjB, OB.map(E.left)))
}

(edit: a little more terse)

This was referenced Jan 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant