import { test } from "../../tests/harness" ; import { GenericMonad , Matchable , Monad } from "./adt" ; const GenericMaybe = < G extends GenericMonad < any > > ( { just , none , match } ) : Monad < G > => { const map = < A , B > ( f ) => match ( { none , just : ( value ) => just ( f ( value ) ) } ) ; const of = just ; const chain = < T , U extends GenericMonad < G > > ( f ) => match ( { none , just : f } ) ; return { map , of , chain } ; } ; const MAYBE = Symbol ( "maybe" ) ; export type Maybe < T > = Just < T > | None ; export interface Just < T > { [ MAYBE ] : T ; } export type None = typeof MAYBE & { [ key ] : never ; } ; declare module "typeprops" { interface TypeProps < T , Params > { "examples/pattern-matching/maybe#maybe" : { infer : T extends Maybe < infer A > ? [ A ] : never ; construct : Maybe < Params [ 0 ] > ; } ; } } const just = < A > ( value ) => ( { [ MAYBE ] : value } as Just < A > ) ; const none = { } as None ; const match = < A , B > ( { just , none } ) => ( maybe ) : B => ( MAYBE in maybe ? just ( ( maybe as Just < A > ) [ MAYBE ] ) : none ) ; export const maybe = { just , none , match } ; const { map , chain , of } = GenericMaybe < Maybe < never > > ( { just , none , match } ) ; test ( "examples/pattern-matching/maybe" , test => { test . plan ( 6 ) ; test . deepEqual < Maybe < number > > ( of ( 44 ) ) ( map ( ( x ) => x + 2 ) ( of ( 42 ) ) ) ; test . deepEqual < Maybe < number > > ( none ) ( map ( ( x ) => x + 2 ) ( none ) ) ; test . deepEqual < Maybe < number > > ( none ) ( chain ( ( x ) => ( x > 40 ? none : of ( x * 2 ) ) ) ( of ( 42 ) ) ) ; test . deepEqual < Maybe < number > > ( of ( 64 ) ) ( chain ( ( x ) => ( x > 40 ? none : of ( x * 2 ) ) ) ( of ( 32 ) ) ) ; test . deepEqual < Maybe < None > > ( of ( none ) ) ( map ( ( x ) => none ) ( of ( 42 ) ) ) ; test . deepEqual < Maybe < Maybe < number > > > ( of ( of ( 84 ) ) ) ( map ( ( x ) => of ( x * 2 ) ) ( of ( 42 ) ) ) ; } ) ;