[Grace-core] Polymorphic/generic classes, etc.
Kim Bruce
kim at cs.pomona.edu
Wed Jun 15 23:21:38 PDT 2011
In this e-mail I show some code using matching and then make a proposal for support for parametric polymorphism.
Our Grace implementation is making good progress. Here is a sample program that compiles (including type-checks) and then runs correctly:
program optionTest{
interface OptionString {
isNone () -> Boolean
getOrElse (s:String) -> String
}
object NoneString implements OptionString {
method isNone() -> Boolean {true}
method getOrElse(default: String) -> String {default}
}
interface SomeStringType {
isNone () -> Boolean
getOrElse (s:T) -> T
}
class SomeString {(x:String) ->
const value:String := x
method isNone() -> Boolean {false}
method getOrElse(def: String) -> String {value}
method get() -> String {value}
method ++(s: String) -> String {value ++ s}
}
object Tests {
method printString(s: OptionString) -> Unit {
match (s) {
case {str: SomeStringType -> print str.get()}
case { (NoneString) -> print "Ignore this line!"}
}
}
var ts: OptionString := SomeString.new("Tim Pawlenty") //boring example string
}
Tests.printString(Tests.ts())
Tests.printString(NoneString)
}
Note that the match statement needed "str: SomeStringType" rather than "str: StringType" because classes can't be used as types. The version using extractor function (not yet implemented) could replace that with case {SomeString(s) -> ...}" using the class rather than type, a generalization that seems useful.
I have a simple proposal (not yet implemented) for parametric polymorphism that can be illustrated by a variant of the same example. Type parameters are enclosed in square brackets.
program optionTest{
interface Option[T] {
isNone () -> Boolean
getOrElse (s:T) -> T
}
object None[T] implements Option[T] { // again not sure if this should be an object or class as will be different objects for
// different types
method isNone() -> Boolean {true}
method getOrElse(default: T) -> T {default}
}
interface SomeType[T] {
isNone () -> Boolean
getOrElse (s:T) -> T
}
class Some[T] {(x:T) ->
const value:T := x
method isNone() -> Boolean {false}
method getOrElse(def: T) -> T {value}
}
object Tests {
method printString(s: Option[String]) -> Unit {
match (s) {
case {str: SomeType[String] -> print str.getOrElse("ERROR")}
case { (None[String]) -> print "Ignore this line!"}
}
}
var ts: Option[String] := Some[String].new("Tim Pawlenty") //boring example string
}
Tests.printString(Tests.ts())
Tests.printString(None[String])
}
--------------------------
Hopefully the example is pretty self-explanatory.
We can also support F-bounded polymorphism (and polymorphic methods) as in the following example:
interface Comparable[T] {
compareTo(T) -> Num
}
class ComparablePair[T,U] implements Comparable[T] // builds new comparable out of a simpler one
where T extends Comparable[T] { // Suggest writing constraint as "where" clause after "implements"
var key: T
var kValue: U
method compareTo(other: ComparablePair[T,U]) -> Num {
key.compareTo(other.key)
}
}
class OrderedList[T] implements OrderedListType[T]
where T extends Comparable[T] {
method add(newT: T) -> Unit {
var next:T = head
...
if (next.compareTo(T) <= 0) then {...}
else {...}
method map[U](f:{(T) -> U}) -> List[U] {...} // notice how write a polymorphic method
}
------------------------
While I would have loved to add a MyType construct, I restrained myself (with some difficulty).
Any comments?
Kim
More information about the Grace-core
mailing list