Skip to content

Instantly share code, notes, and snippets.

@gcanti
Last active May 16, 2021 09:20
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gcanti/56896de8716604e3f8a75edc27f550c4 to your computer and use it in GitHub Desktop.
Save gcanti/56896de8716604e3f8a75edc27f550c4 to your computer and use it in GitHub Desktop.
Monad transformer example (OptionT), Flow and fp-ts, npm install fp-ts
// @flow
import type { Option } from 'fp-ts/lib/Option'
import type { Lazy } from 'fp-ts/lib/function'
import type { Monad } from 'fp-ts/lib/Monad'
import * as optionT from 'fp-ts/lib/OptionT'
import { array } from 'fp-ts/lib/Array'
// If M<A> is a monad then M<Option<A>> is a monad
const optionTArray = optionT.getOptionT(array)
export type URIT = <U, L, A>(x: [U, L, A]) => ArrayOption<A>
export class ArrayOption<A> {
+value: Array<Option<A>>;
constructor(value: Array<Option<A>>) {
this.value = value
}
map<B>(f: (a: A) => B): ArrayOption<B> {
return new ArrayOption(optionTArray.map(f, this.value))
}
ap<B>(fab: ArrayOption<(a: A) => B>): ArrayOption<B> {
return new ArrayOption(optionTArray.ap(fab.value, this.value))
}
chain<B>(f: (a: A) => ArrayOption<B>): ArrayOption<B> {
return new ArrayOption(optionTArray.chain(a => f(a).value, this.value))
}
getOrElseValue(a: A): Array<A> {
return optionT.getOrElseValue(array)(a)(this.value)
}
fold<R>(none: Lazy<R>, some: (a: A) => R): Array<R> {
return optionT.fold(array)(none, some, this.value)
}
}
const map = <A, B>(f: (a: A) => B, fa: ArrayOption<A>): ArrayOption<B> => fa.map(f)
const of = <A>(a: A): ArrayOption<A> => new ArrayOption(optionT.some(array)(a))
const ap = <A, B>(fab: ArrayOption<(a: A) => B>, fa: ArrayOption<A>): ArrayOption<B> => fa.ap(fab)
const chain = <A, B>(f: (a: A) => ArrayOption<B>, fa: ArrayOption<A>): ArrayOption<B> => fa.chain(f)
export const some = of
export const none: ArrayOption<any> = new ArrayOption(optionT.none(array)())
export const fromOption = <A>(oa: Option<A>): ArrayOption<A> => new ArrayOption(optionT.fromOption(array)(oa))
export const liftF = <A>(ma: Array<A>): ArrayOption<A> => new ArrayOption(optionT.liftF(array)(ma))
export interface Instances
extends Monad<URIT> {}
export const arrayOption: Instances = {
map,
of,
ap,
chain
}
console.log(liftF([1, 2, 3]).map(n => n * 2))
/*
[some(2), some(4), some(6)]
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment