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)`

