In this tutorial we're going to build a set of parser combinators.
We'll answer the above question in 2 steps.
- What is a parser?
- and, what is a parser combinator?
So first question: What is parser?
| class Nothing<T> implements PromiseLike<T> { | |
| then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2> { | |
| return (onrejected as any)(this); | |
| } | |
| } | |
| class Just<T> implements PromiseLike<T> { | |
| constructor(private value: T) { } | |
| then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2> { | |
| return (onfulfilled as any)(this.value); | |
| } |
| const fetch = (url) => { | |
| return new Promise((resolve, reject) => { | |
| setTimeout(() => { | |
| console.log(url) | |
| switch(url.match(/\d[aA-zZ]$/)[0]) { | |
| case "1a": | |
| resolve({name: "Seb"}) | |
| // or try this instead: | |
| // reject({error: "something went wrong while fetching " + url}) | |
| break; |
| let cache = new Map(); | |
| let pending = new Map(); | |
| function fetchTextSync(url) { | |
| if (cache.has(url)) { | |
| return cache.get(url); | |
| } | |
| if (pending.has(url)) { | |
| throw pending.get(url); | |
| } |
When defining complex functions in pointfree style, I often find myself switching to pointful style. Sometimes, I even convert to ANF and annotate the types to understand the steps.
After completing the function definition, I often convert back to pointfree style for conciseness. End of the story: To understand it again a couple of weeks later, I start expanding to annotated pointful again.
The small 10-lines library at the end of this post allows to define pointfree functions with intermediate type annotations.
Credits: Agda and EqReasoning for syntactical inspiration.
| open System | |
| open System.Runtime.CompilerServices | |
| type SymbolicException = | |
| { | |
| Source : Exception | |
| Stacktrace : string list | |
| } | |
| module SymbolicException = |
Copyright © 2016-2018 Fantasyland Institute of Learning. All rights reserved.
A function is a mapping from one set, called a domain, to another set, called the codomain. A function associates every element in the domain with exactly one element in the codomain. In Scala, both domain and codomain are types.
val square : Int => Int = x => x * x| using System; | |
| using System.Collections; | |
| using System.Collections.Generic; | |
| namespace Generator3 | |
| { | |
| class Program | |
| { | |
| // classic Generator | |
| static IEnumerable<string> Script() |