Skip to content

Instantly share code, notes, and snippets.

@InPermutation
Forked from brendanzab/stack_edsl.rs
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save InPermutation/9459780 to your computer and use it in GitHub Desktop.
Save InPermutation/9459780 to your computer and use it in GitHub Desktop.
A statically typed, concatenative EDSL in C#.
/// <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