import { Functor, FunctorInstances, map } from './typeclasses/functor' import { Cartesian, product } from './typeclasses/cartesian' import { Apply } from './typeclasses/apply' import { FlatMap, flatMap } from './typeclasses/flatmap' import { Applicative } from './typeclasses/applicative' import { Semigroup, concat, SemigroupInstanceType } from './typeclasses/semigroup' import { Monad } from './typeclasses/monad' import { streamOps, Subject, Stream } from '../xs' import { Plan, Update } from '../interfaces' import { FantasyX } from './fantasyx' import { State } from './state' import { datatype, $, HKT } from './typeclasses' @datatype('Xstream') export class Xstream { streamS: State<$, $> constructor(streamS: State<$, $>) { this.streamS = streamS } filter(f: (a: A) => boolean): Xstream { return new Xstream(Monad.State.map(sa => streamOps.filter(f, sa), this.streamS)) } static fromIntent() { return new Xstream(new State((intent$: $) => ({ s: intent$, a: intent$ }))) } static fromEvent(type: string, name: string, defaultValue?: string) { return new Xstream(new State((intent$: $) => ({ s: intent$, a: streamOps.merge( typeof defaultValue != 'undefined' ? streamOps.just(defaultValue) : streamOps.empty() , streamOps.map((e: Event) => (e.target as HTMLFormElement).value , streamOps.filter((e: Event) => { let target = e.target as HTMLFormElement return target.tagName == 'INPUT' && e.type == type && target.name == name }, (intent$ as $))) ) }))) } static fromPromise(p: Promise) { return new Xstream(new State((intent$: $) => ({ s: intent$, a: streamOps.fromPromise(p) }))) } static from(p: $) { return new Xstream(new State((intent$: $) => ({ s: intent$, a: streamOps.from(p) as $ }))) } toFantasyX() { type itentStream = Subject type updateStream = $> return new FantasyX( new State(intent$ => { let state$ = this.streamS.runA(intent$) return { s: intent$, a: streamOps.map>((a: A) => Applicative.State.pure(a), state$) } })) } } declare module './typeclasses' { export interface _ { "Xstream": Xstream } } declare module './typeclasses/functor' { export namespace Functor { export let Xstream: XstreamFunctor } } export class XstreamFunctor implements Functor<"Xstream">{ map(f: (a: A) => B, fa: Xstream): Xstream { return new Xstream(Monad.State.map(sa => streamOps.map(f, sa), fa.streamS)) } } Functor.Xstream = new XstreamFunctor export class XstreamCartesian implements Cartesian<"Xstream">{ product(fa: Xstream, fb: Xstream): Xstream { return new Xstream( FlatMap.State.flatMap(s1 => ( Functor.State.map(s2 => ( streamOps.combine((a, b) => [a, b], s1, s2) ), fb.streamS) ), fa.streamS)) } } Cartesian.Xstream = new XstreamCartesian declare module './typeclasses/cartesian' { export namespace Cartesian { export let Xstream: XstreamCartesian } } export class XstreamApply implements Apply<"Xstream"> { ap( fab: Xstream B>, fa: Xstream ): Xstream { return new Xstream( FlatMap.State.flatMap(s1 => ( Functor.State.map(s2 => ( streamOps.combine<(a: A) => B, A, B>((a, b) => a(b), s1, s2) ), fa.streamS) ), fab.streamS)) } map = Functor.Xstream.map product = Cartesian.Xstream.product } Apply.Xstream = new XstreamApply declare module './typeclasses/apply' { export namespace Apply { export let Xstream: XstreamApply } } export class XstreamFlatMap extends XstreamApply { flatMap(f: (a: A) => Xstream, fa: Xstream): Xstream { return new Xstream( FlatMap.State.flatMap((a$: $) => ( map<"State", $, $>(i$ => { let sdf = (a: A) => f(a).streamS.runA(i$) return streamOps.flatMap(sdf, a$) }, State.get<$>()) ), fa.streamS) ) } } FlatMap.Xstream = new XstreamFlatMap declare module './typeclasses/flatmap' { export namespace FlatMap { export let Xstream: XstreamFlatMap } } export class XstreamApplicative extends XstreamApply { pure(v: A): Xstream { return new Xstream( Applicative.State.pure(streamOps.just(v)) ) } } Applicative.Xstream = new XstreamApplicative declare module './typeclasses/applicative' { export namespace Applicative { export let Xstream: XstreamApplicative } } export class XstreamMonad extends XstreamApplicative implements FlatMap<"Xstream"> { flatMap = FlatMap.Xstream.flatMap } Monad.Xstream = new XstreamMonad declare module './typeclasses/monad' { export namespace Monad { export let Xstream: XstreamMonad } } export class XstreamSemigroup implements Semigroup> { _T: Xstream concat(fa: Xstream, fb: Xstream): Xstream { return Functor.Xstream.map( ([a, b]) => concat(a, b) , Cartesian.Xstream.product(fa, fb)) } } Semigroup.Xstream = new XstreamSemigroup declare module './typeclasses/semigroup' { export namespace Semigroup { export let Xstream: XstreamSemigroup } }