理解Haskell中($)运算符的类型定义及相关技术问题
($)运算符类型签名相关解答 GHC/Base.hs模块中定义了函数应用运算符($),源码如下:
($) :: forall r a (b :: TYPE r). (a -> b) -> a -> b f $ x = f x
针对相关问题解答如下:
全称量化变量
r的含义r是属于RuntimeRep类的kind级变量,用来标记类型b在运行时的存储方式、求值规则。GHC给不同特征的类型都预设了对应的RuntimeRep取值:普通堆分配的惰性值对应LiftedRep,未装箱的机器整数Int#对应IntRep,未提升严格类型、多态箭头等也有各自对应的表示值。对r做全称量化后,($)就不再被限制在常规值的场景,可以适配任意运行时表示的返回值类型。类型签名
(a -> b) -> a -> b是否具备足够通用性
完全不够。
在GHC默认的kind推导规则下,没有额外标注的类型变量b会被自动约束为Typekind(也就是TYPE LiftedRep),仅支持返回普通惰性堆分配值的函数,没法适配返回未装箱类型、特殊表示类型的函数。举个实际例子,GHC内置的(+#)用来对两个未装箱Int#做加法,返回值也是Int#,如果($)用这个简化签名,写(+# 1#) $ 2#就会直接报kind不匹配的错误,适用范围非常受限。签名中
TYPE的具体含义TYPE是GHC内置的kind级类型族,由编译器原生实现,是运行时表示多态(也就是常说的levity多态)的核心组件。它接收一个RuntimeRep类型的值r作为参数,返回对应类型所属的kind:比如TYPE LiftedRep就是普通开发者最常接触的Typekind(旧写法为*),对应所有常规的惰性lifted类型;TYPE IntRep就是未装箱整数Int#所属的kind。简单说,TYPE r就是「所有运行时表示为r的类型」的kind分类标记。
内容的提问来源于stack exchange,提问作者F. Zer

