类型推断技术及仓颉语言实践

史磊

仓颉语言类型推断技术专家

一、一种看待类型系统的方式

一门编程语言一定得包含类型系统吗?

这个问题今天看来可能显而易见,一个程序没有类型的话还能算是个完整、正确的程序吗?但是其实关于类型系统的作用,一直是存在两种针锋相对的看法的。大家普遍习惯的这种把类型作为程序不可分割的一部分的看待方式叫做“内生”(intrinsic)的理解方式,即一个程序如果没有合法的类型就不能算有意义的程序。而与之相对的,也存在一种“外生”(extrinsic)的理解方式,持这种观点的人认为,程序即使没有类型也同样有意义,类型检查只是额外地证明了这个程序的一些性质,与其他的各种程序分析工具应该处于同样的地位。

姑且不论类型检查是否应该作为一个语言之外的的工具这种工程问题,顺着“类型检查是为了证明了程序的一些性质”这个思路,我们可以得到一些很有趣的认知。

不妨想象一下,一个程序如果在没有类型的情况下就执行起来,会发生什么问题呢?我们有可能给一个函数传入一个整数,但是这个函数实际上却是处理字符串用的,于是它错误地把这个整数形式地数据当做字符串来处理了,最后自然是得不到期望的结果。例如下面的伪代码:

func f(s) {
    s.replace(...)
}
​
let s = f(1)

而在这个过程中加入类型系统的话,如果可以静态地验证这个被调用的函数的形参类型是一个字符串,而每次调用它时实参类型都也是字符串,那么我们就可以保证,在任何情况下执行这个程序,都不会出现把一个整数类型的参数传递给这个处理字符串的函数这种低级错误。

所以这里我们用比较朴素的方式去理解的话,类型系统、尤其是静态类型系统,实际上是一种“程序在运行时处理数据的方式永远不会出错”的证明,如果类型检查可以通过,那么每个数据被传递时,它的提供者和接收者对于这块数据的格式、可以被执行的操作等等的理解总是一致的。实际上,这个性质已经几乎就是一些比较公认的“类型安全”(type safety)的定义了。

另外细心的读者可能会注意到,既然类型系统是一种程序运行时“永远不会出错”的证明,那这个证明完成后,在程序运行时,我们还需要保留“类型”这个东西吗?确实如此,除了为了支持动态派遣等一些动态特性外,大多数静态类型的信息在类型检查完成后对于程序的正确运行就基本没有用处了,理论上是可以被擦除掉的。当然,实际的实现中类型信息对编译优化也有帮助,所以也有语言会选择在后续的编译阶段一直保留它们。

那么我们再回头去看这篇文章最关心的重点问题:类型推断是什么?类型标注又是什么?既然类型检查是一种正确性的证明,那开发者提供的类型标注自然就是手写的部分证明,而类型推断则是一种自动化证明的技术。自动化证明的算法越聪明,必须手写的部分也就越少,能支持的类型特性也就越丰富。实际上,在一些研究性的语言中,类型系统早已超越简单的“处理数据的方式”的正确性证明,还可以包括资源消耗、执行时长、数组长度、值的可空性等等多种方面的正确性证明,其中的类型推断用到的技术与更一般的形式化证明也越来越接近了。

二、仓颉的类型推断需要做什么

在仓颉语言中,类型推断主要起到两个作用,第一是确定每个声明和表达式的类型,这既包括可以省略的变量类型、函数返回类型、泛型实参类型等等,也包括分支、循环、字面量等并不涉及类型标注的各种表达式的类型。第二是帮助确定每个被使用的名字对应的声明,最典型的情况是在调用一个重载的函数时,需要确定调用的具体是哪个定义,另外有些不同种类的定义,如果碰巧名字相同,我们也可能需要借助类型信息来确定使用的究竟是哪个。

三、基于合一(unification)的类型推断

在一些早期的编程语言中,类型之间并没有子类关系,只有相等或不等。时至今日,多数函数式编程语言仍然继承了这个设计思路,包括 Rust 语言如果不考虑生命周期的话,类型之间也没有子类关系。在这些语言中,类型推断普遍是基于合一(unification)过程来完成的。简单来说,即是每当我们遇到一个暂不确定的类型,那就为它引入一个待解的变元,然后在遍历程序的过程中,不断建立起类型变元之间的方程组(如一个函数的形参类型和实参类型必须相等,由此就可以得到一个新的方程),并不断简化这些方程,直到所有类型变元都可以求解出来(或者缺乏足够的信息来求解,此时就会将这样的类型变元泛化,不过这超出本文的讨论范围了),类型推断的过程十分类似于数学上解方程的过程。

这种做法的好处是,这些方程组是从整个程序里所有信息中建立起来的,所以每个未知类型都可以利用全局信息去求解,解出的结果也可以保证是全局正确的。

例如下面这个程序在 Rust 中是可以编译通过的,它可以根据第 5 行的函数调用解出变量 v 需要有 u16 类型。但是等价的程序在一些没有全局的类型推断的语言中则无法通过编译,因为在第 4 行中 v 的类型就已经被推断为整数字面量的默认类型了,这通常是

Nano-ESG数据资源库的构建基于2023年初至2024年秋季期间采集的逾84万条新闻文本,从中系统提炼出企业环境、社会及治理维度的信息。其构建流程首先依据特定术语在德语与英语新闻平台上检索,初步锁定与德国DAX 40成分股企业相关联的报道。随后借助嵌入技术对文本段落执行去重操作,以降低内容冗余。继而采用GLiNER这一跨语言零样本实体识别系统,排除与目标企业无关的文档。在此基础上,通过GPT-3.5与GPT-4o等大规模语言模型对文本进行双重筛选:一方面判定其与ESG议题的相关性,另一方面生成简明的内容概要。最终环节由GPT-4o模型完成,它对每篇文献进行ESG情感倾向(正面、中性或负面)的判定,并标注所涉及的ESG具体维度,从而形成具备时序特征的ESG情感与维度标注数据集。 该数据集适用于多类企业可持续性研究,例如ESG情感趋势分析、ESG维度细分类别研究,以及企业可持续性事件的时序演变追踪。研究者可利用数据集内提供的新闻摘要、情感标签与维度分类,深入考察企业在不同时期的环境、社会及治理表现。此外,借助Bertopic等主题建模方法,能够从数据中识别出与企业相关的核心ESG议题,并观察这些议题随时间的演进轨迹。该资源以其开放获取特性与连续的时间覆盖,为探究企业可持续性表现的动态变化提供了系统化的数据基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值