如何手动计算带类约束的函数应用表达式的类型?
带类约束的函数类型手动计算方法
首先先看无约束场景下的基础函数应用类型规则:
f :: A -> B e :: A ----------- f e :: B
这套规则没有覆盖带*class constraints(类约束)*的函数场景,遇到这类函数时,只要在原有匹配逻辑上补充约束校验、类型替换的步骤就可以手动推导,具体流程是:
- 先把带约束的函数类型拆成两部分:
=>符号前面的是类约束列表,后面的是和普通函数一致的函数签名结构 - 拿实参类型和函数签名里的参数类型做匹配时,把实参的具体类型代换到对应的泛型类型变量上,先校验这个具体类型是否实现了对应的类型类、满足所有相关约束:不满足就直接是类型错误,满足就消掉对应已经匹配完成的类型变量的约束
- 代换完成、消去已满足的约束后,剩下的函数返回类型,就是这次函数应用后的表达式类型
示例推导
我们拿题里的例子一步步算:
已知类型前提:
(+) :: Num a => a -> a -> a 3 :: Int --------------------------- (+) 3 :: ?
推导过程:
- 拆分
(+)的类型:类约束为Num a,也就是类型变量a必须是Num类型类的实例;后面的函数结构是:接收一个类型为a的参数,返回一个a -> a类型的函数 - 匹配第一个入参:实参
3的类型是Int,把泛型变量a替换成Int,先做约束校验:Int本来就是Num类型类的实例,完全满足Num a的要求,这部分约束校验通过 - 做类型代换后消去已满足的约束:原函数结构把
a替换为Int后是Int -> Int -> Int,传入第一个Int类型的参数后,剩余的返回类型就是Int -> Int
最终(+) 3的类型就是Int -> Int。
注:如果传给(+)的第一个参数类型不是Num的实例,比如传一个普通的自定义类型、没有实现Num类型类的方法,就会因为不满足类约束报类型错误。
内容的提问来源于stack exchange,提问作者F. Zer
相关产品推荐
相关产品推荐

