import { Applicative } from "@siteimprove/alfa-applicative" ; import { Array } from "@siteimprove/alfa-array" ; import { Callback } from "@siteimprove/alfa-callback" ; import { Foldable } from "@siteimprove/alfa-foldable" ; import { Functor } from "@siteimprove/alfa-functor" ; import { Iterable } from "@siteimprove/alfa-iterable" ; import { Mapper } from "@siteimprove/alfa-mapper" ; import { Monad } from "@siteimprove/alfa-monad" ; import { Reducer } from "@siteimprove/alfa-reducer" ; import { Thunk } from "@siteimprove/alfa-thunk" ; /**
 *  http public export abstract class Trampoline < T > implements Functor < T > , Applicative < T > , Monad < T > , Foldable < T > , Iterable < T > { protected abstract step ( ) ; public run ( ) { let step = this ; while ( true ) { const next = step . step ( ) ; if ( step !== next ) { step = next ; } else { return next . run ( ) ; } } } public abstract isDone ( ) ; public abstract isSuspended ( ) ; public map < U > ( mapper ) { return this . flatMap ( ( value ) => Done . of ( mapper ( value ) ) ) ; } public apply < U > ( mapper ) { return mapper . flatMap ( ( mapper ) => this . map ( mapper ) ) ; } public abstract flatMap < U > ( mapper ) ; public flatten < T > ( this ) { return this . flatMap ( ( trampoline ) => trampoline ) ; } public reduce < U > ( reducer , accumulator ) { return reducer ( accumulator , this . run ( ) ) ; } public tee ( callback ) { return this . map ( ( value ) => { callback ( value ) ; return value ; } ) ; } public * iterator ( ) { yield this . run ( ) ; } public [ Symbol . iterator ] ( ) { return this . iterator ( ) ; } } public export namespace Trampoline { export function isTrampoline < T > ( value ) ; export function isTrampoline < T > ( value ) ; export function isTrampoline < T > ( value ) { return value instanceof Trampoline ; } export function empty ( ) { return done ( undefined ) ; } export function done < T > ( value ) { return Done . of ( value ) ; } export function suspend < T > ( thunk ) { return Suspend . of ( thunk ) ; } export function delay < T > ( thunk ) { return suspend ( ( ) => done ( thunk ( ) ) ) ; } export function traverse < T , U > ( values , mapper ) { return Iterable . reduce ( values , ( values , value , i ) => values . flatMap ( ( values ) => mapper ( value , i ) . map ( ( value ) => Array . append ( values , value ) ) ) , done ( Array . empty ( ) ) ) ; } export function sequence < T > ( futures ) { return traverse ( futures , ( value ) => value ) ; } } class Done < T > extends Trampoline < T > { public static of < T > ( value ) { return new Done ( value ) ; } private readonly _value : T ; private constructor ( value ) { super ( ) ; this . _value = value ; } protected step ( ) { return this ; } public run ( ) { return this . _value ; } public isDone ( ) { return true ; } public isSuspended ( ) { return false ; } public map < U > ( mapper ) { return new Done ( mapper ( this . _value ) ) ; } public flatMap < U > ( mapper ) { return Suspend . of ( ( ) => mapper ( this . _value ) ) ; } } class Suspend < T > extends Trampoline < T > { public static of < T > ( thunk ) { return new Suspend ( thunk ) ; } private readonly _thunk : Thunk < Trampoline < T > > ; private constructor ( thunk ) { super ( ) ; this . _thunk = thunk ; } protected step ( ) { return this . _thunk ( ) ; } public isDone ( ) { return false ; } public isSuspended ( ) { return true ; } public flatMap < U > ( mapper ) { return Bind . of ( this . _thunk , mapper ) ; } } class Bind < S , T > extends Trampoline < T > { public static of < S , T > ( thunk , mapper ) { return new Bind ( thunk , mapper ) ; } private readonly _thunk : Thunk < Trampoline < S > > ; private readonly _mapper : Mapper < S , Trampoline < T > > ; private constructor ( thunk , mapper ) { super ( ) ; this . _thunk = thunk ; this . _mapper = mapper ; } protected step ( ) { return this . _thunk ( ) . flatMap ( this . _mapper ) ; } public isDone ( ) { return false ; } public isSuspended ( ) { return true ; } public flatMap < U > ( mapper ) { return Suspend . of ( ( ) => Bind . of ( this . _thunk , ( value ) => this . _mapper ( value ) . flatMap ( mapper ) ) ) ; } }