Last active
August 29, 2019 14:49
-
-
Save saulshanabrook/9c5a5c8ef2eb4fa7050a2b0ed4225634 to your computer and use it in GitHub Desktop.
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
export const INVALID = Symbol("INVALID"); | |
/** | |
* Is able to optionally parse from type T to U | |
* and then create U from T. | |
* | |
* The idea is that these functions are inverses of each other: | |
* | |
* parser.create(parser.parse(t)) == t | |
* | |
* as long as parse doesn't return INVALID and | |
* | |
* parser.parse(parser.create(u)) == u | |
*/ | |
class Parser<T, U> { | |
constructor( | |
public parse: (initial: T) => U | typeof INVALID, | |
public create: (parsed: U) => T | |
) {} | |
static identity<T>(): Parser<T, T> { | |
return new Parser(initial => initial, parsed => parsed); | |
} | |
/** | |
* Chains another parser after the current one. | |
* | |
* The idea is that: | |
* | |
* Parser(f, g).then(Parser(h, i)) == Parser(h∘f, g∘i) | |
* | |
* Assuming the composition operator deals with invalid like an optional type. | |
* | |
*/ | |
then<V>(nextParse: Parser<U, V>): Parser<T, V> { | |
return new Parser<T, V>( | |
initial => { | |
const res = this.parse(initial); | |
if (res == INVALID) { | |
return INVALID; | |
} | |
return nextParse.parse(res); | |
}, | |
parsed => this.create(nextParse.create(parsed)) | |
); | |
} | |
} |
@shiftyp thank you! That's exactly what I was looking for... I have ended up just making a specialized version of this for my use case, because otherwise I think the terminology is too much to grok...
Hopefully someday we will be able to express abstract concepts like this without getting weird and academic-y!
I second that hope! That sounds like the right approach. There's a way to make things super generic, but if it hurts understandability then its not all that useful in aggregate. 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This looks similar, but it's a little too academic for me to parse through fully 🤷♂️https://en.wikipedia.org/wiki/Adjoint_functors