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

Static Land style API #285

Open
DylanRJohnston opened this issue Nov 1, 2019 · 2 comments
Open

Static Land style API #285

DylanRJohnston opened this issue Nov 1, 2019 · 2 comments

Comments

@DylanRJohnston
Copy link

DylanRJohnston commented Nov 1, 2019

Hey guys, fp-ts@2.0.0 moved away from a method chaining API to a more static land style API which means it doesn't gel very well with xstream anymore. Would you be opposed to exporting all of operator methods as static functions curried in their stream argument? Right now I have a little helper file that re-exports methods as needed.

e.g.

export const map = <A, B>(f: (a: A) => B)) => ($: Stream<A>): Stream<B> => $.map(F)
@DylanRJohnston
Copy link
Author

DylanRJohnston commented Nov 1, 2019

I'm not sure how to get this to work with operators that work on Streams and MemoryStreams. I see a few different options.

  1. Namespace the operators, something like mapMemory or maybe have them as seperate modules so they can imported as import xs from 'xstream/static' and import xsm from 'xstream/static/memory or something like that.
  2. Use the higher kinded types method developed by fp-ts, but it's pretty difficult to understand for new users and would probably tie these two libraries too close together (Maybe this belongs as a seperate package?)
  3. Use a conditional type for the return. This is in a sense copying the higher kinded type method from fp-ts, but for a known finite domain of Functors. Something like this
type AnyStream<A> = Stream<A> | MemoryStream<A>
type StreamOf<S extends AnyStream<unknown>, B>
  = S extends MemoryStream<unknown> ? MemoryStream<B>
  : S extends Stream<unknown> ? Stream<B>
  : unknown

export const map = <A, B>(f: (a: A) => B) => <S extends Stream<A>>($: S): StreamOf<S, B> => ($.map as any)(f)

I think 3 should work fine given Stream<A> is invariant in A.

@DylanRJohnston
Copy link
Author

DylanRJohnston commented Nov 1, 2019

Just realised Typescript already has pattern matching for types, function overloads!

type AnyStream<A> = Stream<A> | MemoryStream<A>

interface StreamOperator<A, B = A> {
  ($: MemoryStream<A>): MemoryStream<B>
  ($: Stream<A>): Stream<B>
}

export const map = <A, B>(f: (a: A) => B): StreamOperator<A, B> => ($: AnyStream<A>) =>
  ($ as any).map(f)

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

No branches or pull requests

1 participant