Created
June 22, 2018 05:30
-
-
Save babakness/037a34826fe770a4d4ebc36a38b04a7f to your computer and use it in GitHub Desktop.
Working Flatten
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// classes | |
class Just<A> { | |
readonly _A!: A | |
constructor(readonly value: A) {} | |
fold<B>(whenNothing: B, whenJust: (a: A) => B): B { | |
return whenJust(this.value) | |
} | |
map<B>(fn: (a: A) => B): Maybe<B> { | |
return Maybe.of(fn(this.value)) | |
} | |
// makeTrouble<B>(fn: (a: A) => B): Maybe<B> { | |
// return flatten(Maybe.of(fn(this.value))) | |
// } | |
} | |
class Nothing<A> { | |
readonly _A!: A | |
static value: Maybe<never> = new Nothing() | |
private constructor( ) { } | |
fold<B>(whenNothing: B, whenJust: (a: A) => B): B { | |
return whenNothing | |
} | |
map<B>(fn: (a: A) => B): Maybe<B> { | |
return nothing | |
} | |
// makeTrouble<B>(fn: (a: A) => B): Maybe<B> { | |
// return nothing | |
// } | |
} | |
// types | |
export type Maybe<A> = Nothing<A> | Just<A> | |
export type IsNestedMaybe<T> = T extends Maybe<Maybe<any>> ? 'T' : 'F' | |
export type Flatten<T extends Maybe<any>> = { | |
T: Flatten<T['_A']> | |
F: T | |
}[IsNestedMaybe<T>] | |
// values | |
const nothing = Nothing.value | |
const isNully = a => a === undefined || a === null || ( typeof a === 'number' && isNaN( a ) ) | |
const Maybe = { | |
of: <A>(a: A): Maybe<A> => { | |
return isNully(a) ? new Just(a) : nothing | |
} | |
} | |
// functions | |
const isMaybe = <A>( obj : Maybe<A> | any ): obj is Maybe<A> => { | |
return ( obj instanceof Just ) | |
} | |
function flatten<T extends Maybe<any>>(x: T): Flatten<T> { | |
return x.fold(x, a => { | |
if (isMaybe(a)) { | |
return flatten(a) | |
} | |
return x | |
}) | |
} | |
export const head = <A>( arr : A[] ) => arr[ 0 ] | |
export const safeHead = <A>(as: Array<A>): Maybe<A> => { | |
return isNully(as) ? nothing : new Just(head(as)) | |
} | |
// Example 1 -- everything works | |
const foo1 = Maybe.of([1, 2, 3]) | |
.map(safeHead) | |
// foo1 :: Maybe<Maybe<number>> | |
const foo2 = flatten( foo1 ) | |
// foo2 :: Maybe<number> | |
// Example 2 -- wat? | |
// const foo3 = Maybe.of([1, 2, 3]) | |
// .makeTrouble(safeHead) | |
// foo3 :: Maybe<Maybe<number>> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Link to playground https://tinyurl.com/y922gowu