since import { Applicative2 } from 'fp-ts/lib/Applicative' ; import { Apply2 } from 'fp-ts/lib/Apply' ; import { identity } from 'fp-ts/lib/function' ; import { Functor2 } from 'fp-ts/lib/Functor' ; import { HKT , Kind , Kind2 , Kind3 , URIS , URIS2 , URIS3 } from 'fp-ts/lib/HKT' ; import { Monad , Monad1 , Monad2 , Monad2C , Monad3 } from 'fp-ts/lib/Monad' ; data constructor constructor category since export type Free < F , A > = Pure < F , A > | Impure < F , A , any > ; interface Pure < _F , A > { readonly _tag : 'Pure' ; readonly value : A ; } interface Impure < F , A , X > { readonly _tag : 'Impure' ; readonly fx : HKT < F , X > ; readonly f : ( x : X ) => Free < F , A > ; } const impure = < F , A , X > ( fx , f ) : Free < F , A > => ( { _tag : 'Impure' , fx , f } ) ; category since export const liftF = < F , A > ( fa ) : Free < F , A > => impure ( fa , ( a ) => free . of ( a ) ) ; category since export interface FoldFree3 < M extends URIS3 > { < F extends URIS3 , U , L , A > ( nt , fa ) : Kind3 < M , U , L , A > ; < F extends URIS2 , U , L , A > ( nt , fa ) : Kind3 < M , U , L , A > ; < F extends URIS , U , L , A > ( nt , fa ) : Kind3 < M , U , L , A > ; } category since export interface FoldFree2 < M extends URIS2 > { < F extends URIS2 , L , A > ( nt , fa ) : Kind2 < M , L , A > ; < F extends URIS , L , A > ( nt , fa ) : Kind2 < M , L , A > ; } category since export interface FoldFree2C < M extends URIS2 , L > { < F extends URIS2 , A > ( nt , fa ) : Kind2 < M , L , A > ; < F extends URIS , A > ( nt , fa ) : Kind2 < M , L , A > ; } category since export function foldFree < M extends URIS3 > ( M ) ; export function foldFree < M extends URIS2 > ( M ) ; export function foldFree < M extends URIS2 , L > ( M ) ; export function foldFree < M extends URIS > ( M ) ; export function foldFree < M > ( M ) ; export function foldFree < M > ( M ) { return ( nt , fa ) => { if ( isPure ( fa ) ) { return M . of ( fa . value ) ; } else { return M . chain ( nt ( fa . fx ) , ( x ) => foldFree ( M ) ( nt , fa . f ( x ) ) ) ; } } ; } const substFree = < F , G > ( f ) : ( < A > ( fa : Free < F , A > ) => Free < G , A > ) => { function go < A > ( fa ) { switch ( fa . _tag ) { case 'Pure' : return free . of ( fa . value ) ; case 'Impure' : return free . chain ( f ( fa . fx ) , ( x ) => go ( fa . f ( x ) ) ) ; } } return go ; } ; category since export function hoistFree < F extends URIS3 = never , G extends URIS3 = never > ( nt ) ; export function hoistFree < F extends URIS2 = never , G extends URIS2 = never > ( nt ) ; export function hoistFree < F extends URIS = never , G extends URIS = never > ( nt ) ; export function hoistFree < F , G > ( nt ) ; export function hoistFree < F , G > ( nt ) { return substFree ( ( fa ) => liftF ( nt ( fa ) ) ) ; } const map_ = ( fa , f ) => isPure ( fa ) ? free . of ( f ( fa . value ) ) : impure ( fa . fx , ( x ) => free . map ( fa . f ( x ) , f ) ) ; const ap_ = ( fab , fa ) => free . chain ( fab , ( f ) => free . map ( fa , f ) ) ; const chain_ = ( ma , f ) => isPure ( ma ) ? f ( ma . value ) : impure ( ma . fx , ( x ) => free . chain ( ma . f ( x ) , f ) ) ; category since export const map = ( f ) => ( fa ) => map_ ( fa , f ) ; category since export const ap = ( fa ) => ( fab ) => ap_ ( fab , fa ) ; category since export const chain = ( f ) => ( ma ) => chain_ ( ma , f ) ; category since export const flatten = ( mma ) => chain_ ( mma , identity ) ; category since export const of = ( a ) => ( { _tag : 'Pure' , value : a } ) ; category since export const URI = 'Free' ; category since export type URI = typeof URI ; declare module 'fp-ts/lib/HKT' { interface URItoKind2 < E , A > { Free : Free < E , A > ; } } category since export const Functor = { URI , map : map_ } ; category since export const Applicative = { URI , map : map_ , ap : ap_ , of } ; category since export const Apply = { URI , ap : ap_ , map : map_ } ; category since export const free = { URI , ap : ap_ , chain : chain_ , map : map_ , of } ; since export const isPure = < F , A > ( fa ) : fa is Pure < F , A > => fa . _tag === 'Pure' ; since export const isImpure = < F , A > ( fa ) : fa is Impure < F , A , any > => fa . _tag === 'Impure' ;