Skip to content

Instantly share code, notes, and snippets.

@babakness
Created June 22, 2018 05:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save babakness/037a34826fe770a4d4ebc36a38b04a7f to your computer and use it in GitHub Desktop.
Save babakness/037a34826fe770a4d4ebc36a38b04a7f to your computer and use it in GitHub Desktop.
Working Flatten
// 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>>
@babakness
Copy link
Author

Link to playground https://tinyurl.com/y922gowu

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment