# 多态变异体

Felix多态性变体基于Ocaml中的多态性变体。多态变体类型可以从任意构造函数集合中形成。深度和宽度都符合子类型规则。

## 打开/关闭原理

bertrandmeyer在其开创性的著作“面向对象的软件构造”中明确阐述了这一原则。它是一个关键的动机，一个类的想法，提供一个封闭的，或 encapsulated 资源具有一组封闭的指定方法来操作它，同时可以通过继承进行扩展。

### 勤奋的程序员

typedef addable = (
| Val of int
| Add of addable * addable
)
;


fun eval (term: addable) =>
match term with
| Val j => j
| Add (t1, t2) => eval t1 + eval t2
;


typedef subable = (
| Val of int
| Add of subable * subable
| Sub of subable * subable
)
;


fun eval2 (term: subable ) =>
match term with
| Val j => j
| Add (t1, t2) => eval2 t1 + eval2 t2
| Sub (t1, t2) => eval2 t1 - eval2 t2
;


### 懒惰的程序员

typedef addable'[T] = (
| Val of int
| Add of T * T
)
;

fun eval'[T] (eval: T-> int) (term: addable'[T]) : int =>
match term with
| Val j => j
| Add (t1, t2) => eval t1 + eval t2
;

fun eval (term:addable) : int => eval' eval term;


typedef subable'[T] = (
| Sub of T * T
)
;

fun eval2'[T] (eval2: T-> int) (term: subable'[T]) : int =>
match term with
| Sub (t1, t2) => eval2 t1 - eval2 t2
| (addable'[T] :>> y) => eval' eval2 y
;

typedef subable = subable'[subable];
fun eval2 (term:subable) : int => eval2' eval2 term;


## 分型与变异

fun f(x:addable) => eval2 x;


class Abstract {
public: virtual Abstract binop (Abstract const &)const=0;
};

class Derived : public virtual Abstract {
public: Derived binop (Derived const &)const;
};


class Derived : public virtual Abstract {
public: Derived binop (Abstract const &other)const {
Derived *d = dynamic_cast<Derived*>(&other);
if (d) { ... }
else { .. }
}
};


## 混合蛋白

typedef mulable'[T] = (
| Mul of T * T
)
;

fun eval3'[T] (eval3: T-> int) (term: subable'[T]) : int =>
match term with
| Sub (t1, t2) => eval3 t1 - eval3 t2
| (addable'[T] :>> y) => eval' eval3 y
;

typedef mulable = mulable'[mulable];
fun eval3 (term:mulable) : int => eval3' eval3 term;


typedef msable'[T] = (
| subable'[T]
| mulable'[T]
)
;

fun eval4'[T] (eval4: T-> int) (term: msable'[T]) : int =>
match term with
| (subable'[T] :>> y) => eval2' eval4 y
| (mulable'[T] :>> a) => eval3' eval4 z
;

typedef msable = msable'[mslable];
fun eval4 (term:msable) : int  => eval4' eval4 term;


val x = Sub (Add (Val 42, Add (Val 66, Val 99)), Val 23);
val y = Mul (Add (Val 42, Mul (Val 66, Val 99)), Val 23);
val z = Sub (Add (Val 42, Mul (Val 66, Val 99)), Val 23);

println$eval2 x; // subable println$ eval3 y; // mulable

println$eval4 x; // subable println$ eval4 y; // mulable
println\$ eval4 z; // msable
`