import { Stream, streamOps, Subject } from '../xs' import { PlanS } from './interfaces' import { x } from '../x' import { State } from './state' import { Actions, Plan, XcomponentClass, Update } from '../interfaces' import { $ } from './typeclasses' import { map, Functor } from './typeclasses/functor' import { FlatMap, flatMap } from './typeclasses/flatmap' import { Monad } from './typeclasses/monad' import { Cartesian, product } from './typeclasses/cartesian' import { Apply } from './typeclasses/apply' import { Applicative } from './typeclasses/applicative' import { Traversable } from './typeclasses/traversable' import { datatype } from './typeclasses' import { Xstream } from './xstream' import * as React from 'react' @datatype('FantasyX') export class FantasyX { plan: State, $>> constructor(plan: State, $>>) { this.plan = plan } apply(WrappedComponent: XcomponentClass | React.ComponentClass | React.SFC, actions?: Actions) { return x((intent$: Subject) => { return { update$: this.toStream(intent$), actions } })(WrappedComponent) } toStream(intent$: Subject): $> { return streamOps.map, Update>( s => (state => s.patch(a => a).runS(state)), this.plan.runA(intent$)) } map(f: (a: A) => B): FantasyX { return new FantasyX( Functor.State.map(update$ => ( streamOps.map, State>(state => ( Functor.State.map(f, state) ), update$) ), this.plan) ) } foldS(f: (s: S, a: A) => S): FantasyX> { return new FantasyX>( Functor.State.map(update$ => ( streamOps.map, State>>(state => ( state.patch((a: A, s: S) => f(s, a)) ), update$) ), this.plan) ) } combine( f: (a: A, b: B) => C, fB: FantasyX ): FantasyX { return new FantasyX( Monad.State.flatMap(updateA$ => ( Functor.State.map(updateB$ => ( streamOps.combine, State, State>((S1, S2) => ( Monad.State.flatMap(s1 => ( Functor.State.map(s2 => ( f(s1, s2) ), S2) ), S1) ), updateA$, updateB$) ), fB.plan) ), this.plan)) } merge( fB: FantasyX ): FantasyX { return new FantasyX( Monad.State.flatMap(updateA$ => ( Functor.State.map(updateB$ => ( streamOps.merge, State>(updateA$, updateB$) ), fB.plan) ), this.plan)) } } declare module './typeclasses' { export interface _ { "FantasyX": FantasyX } } export class FantasyXFunctor implements Functor<"FantasyX"> { map(f: (a: A) => B, fa: FantasyX): FantasyX { return fa.map(f) } } declare module './typeclasses/functor' { export namespace Functor { export let FantasyX: FantasyXFunctor } } Functor.FantasyX = new FantasyXFunctor export class FantasyXCartesian implements Cartesian<"FantasyX"> { product(fa: FantasyX, fb: FantasyX): FantasyX { return new FantasyX( FlatMap.State.flatMap(s1$ => ( Functor.State.map(s2$ => ( streamOps.combine((a: any, b: any) => Cartesian.State.product(a, b), s1$, s2$) ), fb.plan) ), fa.plan)) } } declare module './typeclasses/cartesian' { export namespace Cartesian { export let FantasyX: FantasyXCartesian } } Cartesian.FantasyX = new FantasyXCartesian export class FantasyXApply implements Apply<"FantasyX"> { ap( fab: FantasyX B>, fa: FantasyX ): FantasyX { return new FantasyX( FlatMap.State.flatMap(s1$ => ( Functor.State.map(s2$ => ( streamOps.combine((s1: any, s2: any) => Apply.State.ap(s1, s2), s1$, s2$) ), fa.plan) ), fab.plan)) } map = Functor.FantasyX.map product = Cartesian.FantasyX.product } declare module './typeclasses/apply' { export namespace Apply { export let FantasyX: FantasyXApply } } Apply.FantasyX = new FantasyXApply export class FantasyXApplicative extends FantasyXApply { pure(v: A): FantasyX { return Applicative.Xstream.pure(v).toFantasyX() } } declare module './typeclasses/applicative' { export namespace Applicative { export let FantasyX: FantasyXApplicative } } Applicative.FantasyX = new FantasyXApplicative