Skip to content

Instantly share code, notes, and snippets.

@xwlee
Last active May 22, 2024 07:22
Show Gist options
  • Save xwlee/8b82ee0c444b28c6b457a2ca75bf1ba3 to your computer and use it in GitHub Desktop.
Save xwlee/8b82ee0c444b28c6b457a2ca75bf1ba3 to your computer and use it in GitHub Desktop.
map-morphism.ts
// List
type List<A> = Nil | Cons<A>;
interface Nil {
readonly _tag: "Nil";
}
interface Cons<A> {
readonly _tag: "Cons";
readonly head: A;
readonly tail: List<A>;
}
const nil: List<never> = { _tag: "Nil" };
// Helpers
const cons = <A>(head: A, tail: List<A>): List<A> => ({
_tag: "Cons",
head,
tail,
});
const isNil = <A>(xs: List<A>): xs is Nil => xs._tag === "Nil";
// Matcher
type Match = <A, B>(
onNil: () => B,
onCons: (head: A, tail: List<A>) => B
) => (xs: List<A>) => B;
const match: Match = (onNil, onCons) => (xs) =>
isNil(xs) ? onNil() : onCons(xs.head, xs.tail);
// Example
const list: List<string> = cons("a", cons("bb", cons("ccc", nil)));
type StrLength = (x: string) => number;
const strLength: StrLength = (x) => x.length;
type MapList = <A, B>(f: (x: A) => B) => (Fx: List<A>) => List<B>;
const map_list: MapList = (f) =>
match(
() => nil,
(head, tail) => cons(f(head), map_list(f)(tail))
);
// strLength: string → number
// listStrLength: List<string> → List<number>
const listStrLength = map_list(strLength);
console.log(listStrLength(list)));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment