Skip to content

Instantly share code, notes, and snippets.

@gbluma
Forked from anonymous/gist:65c37929d31fa0fceb21
Last active August 29, 2015 14:23
Show Gist options
  • Save gbluma/bb1fca6ebb72156beabb to your computer and use it in GitHub Desktop.
Save gbluma/bb1fca6ebb72156beabb to your computer and use it in GitHub Desktop.
An example of Object Algebras in Felix
// Title: An example of Object Algebras in Felix
// Author: Garrett Bluma
// Date: June 29, 2015
// Special thanks to Bruno Oliveira and William Cook for explaining object
// algebras, and for providing examples.
// <http://i.cs.hku.hk/~bruno/oa/>
// -----------------------------------------
// Object algebras use extension via type parameters and inheritance. Given a
// type parameter and an extended algebra, we can calculate with a minimum of
// glue code. We can also extend an algebra via inheritance or type parameters
// without modifying previously written code.
//
// | Lit | Add | Sub (added later)
// Basic | | |
// ExpAlg[Eval] | x | x | x
// ExpAlg[Print] | x | x | x
//
// -----------------------------------------
// Here we define our basic algebra, initially it is completely abstract.
class ExpAlg[E] {
virtual fun Lit : int -> E;
virtual fun Add : E -> E -> E;
}
// EVAL ------------------------------------
typedef Eval = 1 -> int;
// implement the algebra for evaluation for Lit and Add
instance ExpAlg[Eval] {
fun Lit(x:int) => fun () => x;
fun Add(e1:Eval) (e2:Eval) => fun () => e1() + e2();
}
// extended the algebra with subtraction
class SubExpAlg[E] {
inherit ExpAlg[E];
virtual fun Sub : E -> E -> E;
}
// implement the subtraction method for evaluation
instance SubExpAlg[Eval] {
fun Sub(e1:Eval)(e2:Eval) => fun () => e1() - e2();
}
// PRINT -----------------------------------
typedef Print = 1 -> string;
// implement the algebra for printing for Lit and Add
instance ExpAlg[Print] {
fun Lit(x:int) => fun () => str(x);
fun Add(e1:Print)(e2:Print) => fun () => str(e1()) + " + " + str(e2());
}
// implement the subtraction method for printing
instance SubExpAlg[Print] {
fun Sub(e1:Print)(e2:Print) => fun () => str(e1()) + " - " + str(e2());
}
// DEMO -------------------
class EvalUsage {
inherit ExpAlg[Eval];
// when treated as evaluation, the number sum
var v1 = Add (Lit 3) (Lit 4);
println$ v1(); // => 7
}
class PrintUsage {
inherit SubExpAlg[Print];
// when treated as printable, the numbers concatenate
var v2 = Sub (Lit 3) (Lit 4);
println$ v2(); // => 3 - 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment