4.7 F-Bounded Polymorphism
comparable
class into Cecil, introducing an explicit formal parameter for the implied self
argument, might lead to the following declarations:
Unfortunately, each of these definitions of operations on comparable objects is asymmetric: the first argument determines the instantiating type forabstract object
comparable[T];signature = (x@:comparable['T], y@:T):bool; method !=(x@:comparable['T], y@:T):bool {
not(x = y) }
signature < (x@:comparable['T], y@:T):bool; method <=(x@:comparable['T], y@:T):bool {
x = y | x < y }method >=(x@:comparable['T], y@:T):bool {
x = y | x > y }method > (x@:comparable['T], y@:T):bool {
y < x }
comparable
, which then constrains the type of the second argument. This is contrary to the Cecil philosophy of treating arguments symmetrically. Additionally, the body of the >
method does not typecheck, since the signature <(T, comparable[T])
is not defined, only <(comparable[T], T)
.The following revised implementation of comparable treats arguments uniformly:
Unfortunately, it is not legal Cecil: it binds the same type variable twice in the same scope. If such as facility were legal, with the semantics that the system would find a single most-specific type to bind toabstract object
comparable[T];signature = (x@:comparable['T], y@:comparable['T]):bool; method !=(x@:comparable['T], y@:comparable['T]):bool {
not(x = y) }
signature < (x@:comparable['T], y@:comparable['T]):bool; method <=(x@:comparable['T], y@:comparable['T]):bool {
x = y | x < y }method >=(x@:comparable['T], y@:comparable['T]):bool {
x = y | x > y }method > (x@:comparable['T], y@:comparable['T]):bool {
y < x }
T
that enables both formal type patterns to match, then mixed-type comparisons would work correctly. The system would locate a single type to which both argument comparable
types can be instantiated. For the case of comparing integers to reals, this common type is num
.
In a similar fashion, if multiple bindings of the same type variable were allowed, min
could be written using only implicit type parameters:
method
min(x1:'T1 <= comparable['T], x2:'T2 <= comparable['T]):T1|T2 {
if (x1 < x2, { x1 }, { x2 })}
This definition of min
is more convenient than the earlier definition because it does not require the caller to provide an explicit type parameter.
Since these kinds of non-linear type patterns appear to resolve several problems with types such as comparable
, we are investigating the feasibility of extending Cecil to support them.
Generated with Harlequin WebMaker