Hacker News new | ask | show | jobs
by monzee 1964 days ago
You can generalize this with TS's fancy mapped types:

    type Sum<K> = <T> (cases: Pattern<K, T>) => T
    type Pattern<K, T> = {
      [V in keyof K]: K[V] extends any[] ? (...args: K[V]) => T : never
    }
which takes TS very close to ML:

    type Shape = Sum<{
      circle: [number, number, number],
      rectangle: [number, number, number, number]
    }>

    function Circle(x: number, y: number, r: number): Shape {
      return ({ circle }) => circle(x, y, r);
    }

    function Rectangle(x: number, y: number, w: number, h: number): Shape {
      return ({ rectangle }) => rectangle(x, y, w, h);
    }

    function area(shape: Shape): number {
      return shape({
        circle: (x, y, r) => Math.PI * r * r,
        rectangle: (x, y, w, h) => w * h
      });
    }