Last active
January 31, 2022 22:45
-
-
Save tabatkins/d974137e9ab0272acb3e57cccde99300 to your computer and use it in GitHub Desktop.
ADT, Decorators, Pattern Matching
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
// This is a decorated version of <https://github.com/tc39/proposal-pattern-matching#custom-matcher-protocol-interpolations> | |
// A predefined ADT decorator. | |
// Use it on static "constructor" methods only. | |
// Pass an extractor function, to produce a pattern-matching value. | |
// The instance must have an [ADT.kind] property | |
// set to the constructor method used. | |
const ADT = (valExtractor=()=>null) => (_, {methodName, isStatic, kind, addInitializer}) => { | |
if(kind == "method" && isStatic) { | |
addInitializer(function(){ | |
// `this` is the class | |
const cls = this; | |
const method = cls[methodName]; | |
method[Symbol.matcher] = (matchable) => { | |
if(matchable instanceof cls && matchable[ADT.kind] == method) { | |
return {matched: true, value:valExtractor(matchable)}; | |
} | |
return {matched:false}; | |
} | |
}); | |
} else { | |
throw new Exception("only usable on static methods"); | |
} | |
} | |
ADT.kind = new Symbol("ADT kind"); | |
class Option { | |
constructor(kind, val) { | |
this[ADT.kind] = kind; | |
if(this[ADT.kind] == Option.Some) { | |
this._value = val; | |
} | |
} | |
get value() { | |
if(this.isSome()) return this._value; | |
throw new Exception("Can't get the value of an Option.None."); | |
} | |
get isSome() { | |
return this[ADT.kind] == Option.Some; | |
} | |
@ADT(x=>x.value) | |
static Some(val) { | |
return new Option(Option.Some, val); | |
} | |
@ADT() | |
static None() { | |
return new Option(Option.None); | |
} | |
} | |
match(result) { | |
when (${Option.Some} with val) -> console.log(val); | |
when (${Option.None}) -> console.log("none"); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment