-
-
Save gbluma/bb1fca6ebb72156beabb to your computer and use it in GitHub Desktop.
An example of Object Algebras in Felix
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
// 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