Skip to content

Instantly share code, notes, and snippets.

@Willmo36
Created December 4, 2018 11:04
Show Gist options
  • Save Willmo36/56f6f6805e9923357b24a14b5795f479 to your computer and use it in GitHub Desktop.
Save Willmo36/56f6f6805e9923357b24a14b5795f479 to your computer and use it in GitHub Desktop.
SKI combinators in TypeScript
type K = <A>(a: A) => <B>(b: B) => A;
type S = <A, B, C>(abc: (a: A) => (b: B) => C) => (ab: (a: A) => B) => (a: A) => C;
const K: K = a => b => a;
const S: S = abc => ab => a => abc(a)(ab(a));
type IGNORED = "ignored";
function IforallT<T>(t: T): (t: T) => T {
//To make I from S we need to achieve
//a :: T, b is ignored, c == a :: T
//if b is ignored then the ab arg of S becomes irrelevant,
//we just need to put "something" in there
//"something" == K | S, let's use K
//bcz of typescript we need to keep track of the useless part of this K, it's b -> a part.
//we can do that by using ReturnType of K, since it's curried it'll turn the a->b->a into b->a
//back to S
//the b arg of S === ReturnType<K>
//so the a arg of S === a -> ReturnType<K> -> a
//which fits the definition of K perfectly
const K1 = (T: T) => (y: IGNORED) => T;
const K2 = (T: T) => (y: ReturnType<typeof K1>) => T;
const I: (t: T) => T = S(K2)(K1);
return I;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment