User:Kevin Reid/Defining algebraic data types
From Erights
Quite incomplete, but better here than on my hard disk. Top is the partial implementation, bottom is some possible actual usage interfaces:
def ne(s) { return makeNounExpr(s, null, s) } def algebraic(constructors :List[String]) { def constrSet := constructors.asSet() return def aGenMap { to fetch(`make$upperName`, _) { def lowerName := upperName(0,1).toLowerCase() + upperName(1) require(lowerName != upperName) def upperNoun := ne(upperName) def prog := e` interface $upperNoun guards ${ne(`${upperName}Stamp`)} {} return def ${ne(`make$upperName`)} { to asType() { return $upperNoun } match [constr ? constrSet.contains(constr), args] { return def ad implements AdStamp { ... } } match [`match__@constr/@n` ? constrSet.contains(constr), [specimen, ejector]] { ... } } ` return prog.eval(safeScope) } to without(n) { # underconstrained return [].asMap() } } } # Haskell: "data Either a b = Left a | Right b" def [=> makeEither] := algebraic(["left", "right"]) def [=> makeEither] := algebraic`a b -> left(a) | right(b)`