Created
September 25, 2017 16:20
-
-
Save robsimmons/5b1a5b69d820bc12ecbf9a176be64d69 to your computer and use it in GitHub Desktop.
Typescript discriminated unions example (ropes)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A non-empty rope is either a leaf (string) or a node with two children | |
// that are both non-empty ropes | |
interface Tagged<T> { | |
tag: T; | |
} | |
type RopeNode = | |
| Tagged<"node"> & { | |
left: RopeNode; | |
right: RopeNode; | |
} | |
| Tagged<"leaf"> & { | |
data: string; | |
}; | |
// An empty string is represented by the rope null | |
type Rope = RopeNode | null; | |
function concat(r1: Rope, r2: Rope): Rope { | |
if (r1 === null) return r2; | |
if (r2 === null) return r1; | |
return { tag: "node", left: r1, right: r2 }; | |
} | |
function impossible(x: never): never { | |
throw new Error("Unexpected object: " + x); | |
} | |
function max(x: number, y: number): number { | |
if (x > y) return x; | |
else return y; | |
} | |
function height(r: Rope): number { | |
if (r === null) return 0; | |
switch (r.tag) { | |
case "leaf": | |
return 1; | |
case "node": | |
return 1 + max(height(r.left), height(r.right)); | |
default: | |
return impossible(r); | |
} | |
} | |
function ropeToString(r: Rope): string { | |
if (r === null) return ""; | |
switch (r.tag) { | |
case "leaf": | |
return r.data; | |
case "node": | |
return ropeToString(r.left) + ropeToString(r.right); | |
default: | |
return impossible(r); | |
} | |
} | |
function leaf(s: string): RopeNode { | |
return { tag: "leaf", data: s }; | |
} | |
function node(r1: RopeNode, r2: RopeNode): RopeNode { | |
return { tag: "node", left: r1, right: r2 }; | |
} | |
let r = node(node(leaf("a"), node(leaf("b"), leaf("c"))), leaf("d")); | |
console.log(height(r)); | |
console.log(height(concat(r, concat(r, r)))); | |
console.log(ropeToString(r)); | |
console.log(ropeToString(concat(r, concat(r, r)))); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment