[Grace-core] "Object Algebras" in Grace
James Noble
kjx at ecs.vuw.ac.nz
Fri Jun 29 19:43:40 PDT 2012
Hi all
Here's a somewhat random email that's been in draft since Beijing.
Realizing I could talk to WIlliam about this tomorrow encouraged
me to send this today L-)
J
-----
I've been talking to people about Bruno & William's Object Algebra paper at ECOOP.
(version here http://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf)
one thing I noticed is that this is similar to the newspeak module
design - a module is a class, it's constructor takes the "platform"
which is basically a factory for every object in the program
http://bracha.org/newspeak-modules.pdf
my big question - since we're talking about a somewhat similar design for Grace -
is how e.g. this relates to the kind of nesting / implicit parameterisation you get
with object nesting / family polymorphism? The context is that we're looking at
module design for Grace, and are wondering how to do it.
I also typed up a small implementation of half of the example in the paper in Grace.
(Half because that's as far as I got in Beijing; there'd be no problem doing the rest)
Currently without types because our generic typechecker isn't done yet.
But this does work, and shows the topology. One odd aspect
of this implementation - it's not about object algebras per se, but
rather about Grace's "encoding" of classes as objects - a classes-as-methods
encoding would make object algebras' code a little cleaner still.
In Grace you write "factory.lit(3)" as a "constructor" call but that is defined
in terms of "Lit.new(3)" the "new" method to a class.
Of course, I guess one could call the sole constructor "lit" too,
so you'd write Lit.lit(3).
hmm...
James
This should work if you cut & paste into the top-left box of
http://homepages.ecs.vuw.ac.nz/~mwh/minigrace/js/
// "Fig.1 An object-oriented encoding of integer expressions"
type Exp = { eval }
print "basic composite data"
class Lit.new(n : Number) -> Exp {
def eval = n
}
class Add.new(l',r') -> Exp {
def l = l'
def r = r'
method eval {l.eval+ r.eval}
}
print "used direcly"
print ( Add.new(Lit.new(3), Lit.new(5)).eval )
print "Fig.2 Visitor interface for arithmetic expressions (also an object algebra interface)"
type IntAlg<A> = {
lit(x : Number) -> A
add(e1 : A, e2 : A) -> A
}
print "Fig.3. Using an object algebra as a factory"
class IntFactory.new -> IntAlg<Exp> {
method lit(x : Number) -> Exp { Lit.new(x) }
method add(e1 : Exp, e2 : Exp) -> Exp { Add.new(e1, e2) }
}
print "used via a factory"
def f = IntFactory.new
print ( f.add(f.lit(3), f.lit(5)).eval )
print "a function parametric in the factory - types omitted as grace doesn't do generic"
method exp(v) {return v.add(v.lit(3), v.lit(5))}
print "called function with factory"
print (exp(f).eval)
print "Fig.4 A retroactive implementation of printing for arithmetic expressions"
type Print = {
printString -> String
}
class IntPrint.new {
method lit(x : Number) {
return object { method printString -> String {return "{x}"} } }
method add(e1 : Print, e2 : Print) {
return object { method printString -> String {return "{e1.printString} + {e2.printString}"} } }
}
def p = IntPrint.new
print (exp(p).printString)
print "Fig.5 Adding a printing operation"
class Print2.new {
method lit(x : Number) {return "{x}"}
method add(e1 : Print, e2 : Print) {return "{e1} + {e2}"}
}
def print2 = Print2.new
print (print2.lit(333))
print "Fig. 6 Adding boolean expressions"
class Bool.new(b : Boolean) -> Exp {
def eval = b
}
class Iff.new(e1',e2',e3') {
def e1 = e1'
def e2 = e2'
def e3 = e3'
method eval {if (e1.eval) then {e2.eval} else {e3.eval}}
}
print "done"
More information about the Grace-core
mailing list