行多态性

Polyrecord参数

行多态性为记录子类型化提供了一种替代方法,在这种方法中,尽管客户机函数不单独知道它们,但它们作为组保存,而不是子类型强制。下面是一个简单的例子:

typedef point = (x:int, y:int);
typedef coloured_point = (x:int, y:int, colour: int);
typedef elevated_point = (x:int, y:int, z:int);

fun step_right[T] (a : (x:int, y:int | T)) => (a with x=a.x+1);

var cp : coloured_point = (x=0, y=0, colour=42);
var ep : elevated_point = (x=0, y=0, z=100);

println$ cp.step_right._strr;
println$ ep.step_right._strr;

这里,类型T将是一个记录类型,它包含参数类型的所有字段,而不是 xy . 这可能因呼叫而异。与子类型化不同,实际参数是用一个函数更新更新的,它保留了所有原始字段,即使是函数不知道的字段。

这里的参数类型称为polyrecord类型,它由通常的记录字段列表和一个竖线组成,后跟另一个类型,可以是类型变量,如示例所示。

多记录值

Polyrecord类型是普通类型,可以为其定义值:

var a = (x=1, y=2 | (e=42));

垂直条的RHS上的值类型必须在单态化后解析为记录、元组、数组或单元,包括递归解析的polyrecord。

与对象一起使用

因为对象类型只是记录类型,所以行多态性可以用于对象。例如:

object coloured_point (var x:int, var y:int, var colour: int) {
  method fun getx () => x;
  method proc setx (newx: int) { x = newx; }
  method proc show { println$ "x=" + x.str + ", y="+y.str + ",colour=" + colour.str; }
};

proc step_right[T] (a : (getx: 1-> int, setx: int->0 | T)) {
  a.setx (a.getx() + 1);
}

var cp = coloured_point (x=0,y=0,colour=42);
cp.step_right;
cp.show();