-
-
Save InPermutation/9459780 to your computer and use it in GitHub Desktop.
A statically typed, concatenative EDSL in C#.
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
/// <summary>Used to enforce type nesting</summary> | |
public interface HList { } | |
public class Empty : HList { } | |
public class Stack<T, TChild> : HList where TChild : HList | |
{ | |
public T Item { get; private set; } | |
public TChild Child { get; private set; } | |
public Stack(T item, TChild child) | |
{ | |
this.Item = item; | |
this.Child = child; | |
} | |
} | |
class Program | |
{ | |
Stack<T, TChild> Push<T, TChild>(T item, TChild child) where TChild : HList | |
{ | |
return new Stack<T, TChild>(item, child); | |
} | |
TChild Pop<TIgnore, TChild>(Stack<TIgnore, TChild> stack) where TChild : HList | |
{ | |
return stack.Child; | |
} | |
Stack<T, Stack<T, TChild>> Dup<T, TChild>(Stack<T, TChild> stack) where TChild : HList | |
{ | |
return Push(stack.Item, stack); | |
} | |
Stack<T2, Stack<T1, TChild>> Swap<T1, T2, TChild>(Stack<T1, Stack<T2, TChild>> stack) where TChild : HList | |
{ | |
return Push( | |
stack.Child.Item, | |
Push( | |
stack.Item, | |
stack.Child.Child)); | |
} | |
Stack<bool, TChild> Eq<T, TChild>(Stack<T, Stack<T, TChild>> stack) | |
where TChild : HList | |
where T : IEquatable<T> | |
{ | |
return Push( | |
stack.Item.Equals(stack.Child.Item), | |
stack.Child.Child); | |
} | |
// no generic "addable" type; implement one for strings and one for ints | |
Stack<int, TChild> Add<TChild>(Stack<int, Stack<int, TChild>> stack) where TChild : HList | |
{ | |
return Push( | |
stack.Item + stack.Child.Item, | |
stack.Child.Child); | |
} | |
Stack<string, TChild> Add<TChild>(Stack<string, Stack<string, TChild>> stack) where TChild : HList | |
{ | |
return Push( | |
stack.Item + stack.Child.Item, | |
stack.Child.Child); | |
} | |
// no generic "multiplicable" type | |
Stack<int, TChild> Mul<TChild>(Stack<int, Stack<int, TChild>> stack) where TChild : HList | |
{ | |
return Push( | |
stack.Item * stack.Child.Item, | |
stack.Child.Child); | |
} | |
Stack<int, TChild> Square<TChild>(Stack<int, TChild> stack) where TChild : HList | |
{ | |
return Mul(Dup(stack)); | |
} | |
static void Main(string[] args) | |
{ | |
// bah, too lazy to go write `static` everywhere | |
new Program().Main(); | |
} | |
void Main() | |
{ | |
var empty = new Empty(); | |
var eight = Push(8, empty); | |
var e_t = Push(3, eight); | |
// all types are correctly inferred; this one is explicitly specified for funsies. | |
Stack<int, Stack<int, Stack<int, Empty>>> e_t_t = Dup(e_t); | |
var added = Add(e_t_t); | |
var multiplied = Mul(added); | |
Stack<int, Empty> squared = Square(multiplied); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment