Created
April 16, 2013 20:34
-
-
Save puffnfresh/5399419 to your computer and use it in GitHub Desktop.
Automatically deriving a catamorphism from a closed interface.
This file contains hidden or 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
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 | |
} |
This file contains hidden or 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
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