User:Kevin Reid/Defining algebraic data types

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 } } }


 * 1) Haskell: "data Either a b = Left a | Right b"

def [=> makeEither] := algebraic(["left", "right"]) def [=> makeEither] := algebraic`a b -> left(a) | right(b)`