Open gabejohnson opened 6 years ago
Hey @gabejohnson, thanks for opening this. I've been watching https://github.com/fantasyland/fantasy-land/pull/286 closely. It'd currently be much simpler for @most/core
to implement static-land (it mostly already does, but of
is named now
) than fantasy-land 3.x, since @most/core
streams don't share a common prototype (they only share an interface).
Hence my interest in https://github.com/fantasyland/fantasy-land/pull/286. We'll continue keeping an eye on it.
I've toyed around with two approaches integrating Fantasyland support. Both are backwards compatible. I guess, I'd favour the separate package approach (A), since it's not invasive.
Stream
with class FantasyLandStream <A>
FL<A>
Stream class which delegates FL method calls to @most/core functions. See discussion and playground code// FL-API.ts
import FantasyLandStream from 'FLDelegate'
import { periodic as _periodic, take as _take, … } from '../core/src/index'
import { compose, curry2, curry3 } from '@most/prelude'
export const fantasyLand = <A>(stream: Stream<A>) =>
new FantasyLandStream(stream);
// Number -> FantasyLandStream ()
export const periodic = compose(fantasyLand, _periodic)
interface Tap {
<A>(f: (a: A) => any, s: Stream<A>): FantasyLandStream<A>
<A>(f: (a: A) => any): (s: Stream<A>) => FantasyLandStream<A>
}
export const tap: Tap = curry2((x, y) => fantasyLand(_tap(x, y)))
// …
// FLDelegate.ts
export class FantasyLandStream<A> implements Stream<A>, FunctorFantasyLand<A> {
constructor(private readonly stream: Stream<A>) {}
run(sink: Sink<A>, scheduler: Scheduler): Disposable {
return this.stream.run(sink, scheduler)
}
['fantasy-land/map']<B>(fn: (value: A) => B): FantasyLandStream<B> {
return fantasyLand<B>(map(fn, this.stream))
}
//…
}
Stream<A>
with class FL<A> implements Stream<A>
map
, empty
,…) into a single source FL.ts
(must be a single file to avoid circular dependencies)Stream<A>
with FL<A>
Stream<A>
implementations
extends Stream<A>
with implements FL<A>
super()
call// FL.ts
export abstract class FL<A> implements Stream<A> {
['fantasy-land/map']<B>(fn: (a: A) => B): FL<B> {
return Map.create<A, B>(fn, this)
}
['fantasy-land/empty'](): FL<never> {
return new Empty()
}
// …
_T?: A
abstract run (sink: Sink<A>, scheduler: Scheduler): Disposable
}
class Map<A, B> extends FL<B> {
//…
// transform.ts
import { FL, Map } from 'FL'
export const map = <A, B>(f: (a: A) => B, stream: Stream<A>): FL<B> =>
Map.create(f, stream)
// …
Continuing the conversation from https://github.com/cujojs/most/pull/347