欢迎光临散文网 会员登陆 & 注册

Ruby 实现多态,用匹配子来理解类型理论——类型论(二)

2023-06-16 08:24 作者:花角  | 我要投稿

目录:

- Haskell 类型系统的不足

- Ruby 函数多态的类型实现 | 类型 与 Matchy,参数 与 Serie

- 实现 参数数量的多态


Haskell 的函数的类型如下,它可以实现类型多态

我们把这六个分支叫做函数的分态 或者 分支函数

但我们不可以进行如下定义:

因为 Haskell 的所有函数本质都是一元函数,这是它实现 函数curry(柯里)化 的理论和原理。

二元函数接受一个值,返回一个一元函数。

因为 func 接受一个 int 值之后,无法确定 要返回 int 还是 int -> int

因此,Haskell 无法完美实现 参数数量的多态。

我们要实现 更完全 的多态,不能使用 函数纯一元 的设定。

如 Ruby 要实现数量多态是这样的。

如下,是一个合法的 Ruby 函数定义和其调用。

我们把定义部分的 (a, b, c, *args, &blk),叫做 匹配子(Matchy)

而调用部分的 (a, b, c, d, e) 叫做 Serie(系列)。

blk.call(...)中的(a, b, [c, *args].sum) 叫做 打包(Packy)

Serie 需要通过 匹配子 匹配成功后,才能成功地调用 函数

之后 Serie 经过 打包,传输给 函数体进行处理。

这里,匹配子 等同于 函数的类型。


Serie -> Matchy -> Packer -> Proc

之后 Proc 再输出 Serie 给调用这个函数的函数。


为方便起见,匹配子的书写为 Matchy(...)

系列的书写为 Serie(...)

现在,我们要在 Ruby 中实现复杂的函数多态系统。

这是我自己写的一个库。

着手用 Ruby 实现函数多态

我们可以在 Ruby 中 定义函数多态,以代替在函数内部重复书写的 if-else,

以及每次增加新功能都要增改函数定义、或者 给原函数起别名 的麻烦。

其中 Numeric, Numeric, Numeric => Numeric是 匹配子。

这个匹配子包含了返回值类型,用以根据调用它的下游函数所需要的参数类型,返回特定的分态

可以看到,伪关键字 main 表示函数的主函数,而 mu 则表示分支函数。这个main mu 在具体的实现上只是一种语法盐,方便理清关系。

Numeric, Numeric, Numeric 是函数的输入匹配子。

=> 右边的 Numeric 是函数的返回匹配子。

这表明,log 如果接受三个 Numeric 参数,以及下游调用者需要一个 Numeric 参数

则 调用 模式为 Matchy( Numeric, Numeric, Numeric => Numeric )的分支函数 进行计算。

(但是目前只实现了参数多态,尚未实现返回值多态)

可知,Numeric 是一个类(Class),而 1, 2, 3 是他的实例。

在Ruby 中,任何类的类都是类类(Class),都是Class 的实例,而任何不是类的对象,都可以当作值。

Ruby 的模式匹配是

类类的实例 匹配 他的实例,即,类 匹配于 其 实例。

类类 匹配 类。

可以看到

Class 不是 任何非类实例的超父类

1. 类自身 无法匹配 类自身

2.         可以匹配 类实例

3. 非类实例  可以  匹配  非类实例自身

如何让 Numeric 匹配 Numeric 

这时,需要指示 匹配函数,match(matchy, serie),matchy 中的类当作非类实例看待。

Just(Numeric) 可以匹配 Numeric

目前还没有实现 in 的这个功能。

Just(Numeric) 等价于 Numeric 的单例类。所以可以匹配成功。

理论上,匹配子 1, 2 表示匹配12的实例。而 1 2 不是类,显然没有实例。

但在Ruby中,非类实例 的匹配其自身。

因此不需要写 Just(1), Just(2)Matchy(1, 2) 就可以 匹配 Serie(1, 2) 了。

参数数量标记,用 正则表达式 来理解

Numeric {3} 表示 接收三个连续的 Numeric 实例

Numeric * 表示接受0个或多个连续的 Numeric 实例

在 Ruby 中的写法是

Some(quant, class) 指示 匹配0到2个连续的 Float 实例

当输入的参数 Serie 匹配于 Matchy(Float, Some(..2, Float))时,就会调用该函数。

那么,假设 函数对 参数的部分顺序并不关心,该如何描述呢?

例如,加法,排序函数。

无论输入的参数是怎样的顺序,输出的结果都是一样。

下回:更复杂的类型实现:

- 交换律、结合律、幂律....

- 类型的并、单匹配子,母匹配子,子匹配子,匹配子的解茧。

Ruby 实现多态,用匹配子来理解类型理论——类型论(二)的评论 (共 条)

分享到微博请遵守国家法律