Skip to content

Instantly share code, notes, and snippets.

@puffnfresh
Created April 16, 2013 20:34
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save puffnfresh/5399419 to your computer and use it in GitHub Desktop.
Save puffnfresh/5399419 to your computer and use it in GitHub Desktop.
Automatically deriving a catamorphism from a closed interface.
package precog.macro;
import haxe.macro.Expr;
import haxe.macro.Context;
class Catamorphism {
#if macro
public static function build(classes: Array<String>) {
var fields = Context.getBuildFields();
fields.push(cataMethod(classes, null));
return fields;
}
public static function autoBuild(classes: Array<String>) {
var fields = Context.getBuildFields();
var name = Context.getLocalClass().get().name;
var index = Lambda.indexOf(classes, name);
fields.push(cataMethod(classes, macro return $i{'_${index}'}($i{"this"})));
return fields;
}
static function cataMethod(classes: Array<String>, body: Expr): Field {
var types = classes.map(function(s: String) return Context.getType(s));
var a = TPath({name: 'A', pack: [], params: []});
var args = [];
for(index in 0...classes.length) {
var className = classes[index];
args.push({
name: '_${index}',
type: TFunction([Context.toComplexType(types[index])], a),
opt: false,
value: null
});
}
return {
name: "cata",
access: [APublic],
pos: Context.currentPos(),
kind: FFun({
args: args,
expr: body,
params: [{name: 'A'}],
ret: a
})
};
}
#end
}
package;
@:build(precog.macro.Catamorphism.build(['A', 'B']))
@:autoBuild(precog.macro.Catamorphism.autoBuild(['A', 'B']))
interface Closed {
function hello(): String;
}
class A implements Closed {
public function hello() return "Hello from A";
}
class B implements Closed {
public function hello() return "B does not say Hello";
public function world() return "Special B function";
}
class MyApp {
static function something(closed: Closed) {
var output = closed.cata(
function(a: A) return a.hello(),
function(b: B) return b.world()
);
trace(output);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment