为何GHC无法解析此类型族实例?
GHC类型族实例类型匹配失败的原因
问题场景
以下代码中,尽管已经声明了type instance Obj Hask = *,GHC仍拒绝通过Arr Hask的类型实例声明,报错提示无法匹配Obj Hask和*:
{-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} module Minimal where type family Obj t :: * type family Arr t :: Obj t -> Obj t -> * data Hask type instance Obj Hask = * type instance Arr Hask = (->)
对应的报错信息:
Minimal.hs:15:26: error: • Couldn't match kind ‘Obj Hask’ with ‘*’ Expected kind ‘Obj Hask -> Obj Hask -> *’, but ‘(->)’ has kind ‘* -> * -> *’ • In the type ‘(->)’ In the type instance declaration for ‘Arr’ | 15 | type instance Arr Hask = (->) | ^^^^
然而,通过StandaloneKindSignatures扩展定义中间类型Function后,代码可以正常编译:
{-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} module Minimal where type family Obj t :: * type family Arr t :: Obj t -> Obj Hask -> * data Hask type instance Obj Hask = * type Function :: Obj Hask -> Obj Hask -> * type Function = (->) type instance Arr Hask = Function
原因解析
核心问题在于GHC在检查类型族实例的等式时,不会自动展开右侧的类型族实例来进行kind匹配:
- 当直接写
type instance Arr Hask = (->)时,GHC首先会根据Arr的声明,要求右侧的类型必须具有Obj Hask -> Obj Hask -> *的kind。 - 此时GHC不会主动将
Obj Hask展开为*(尽管我们已经定义了对应的实例),它只会把Obj Hask当作一个尚未解析的kind变量,因此无法和(->)的* -> * -> *kind匹配,最终报错。
而使用中间类型Function的方式之所以可行,是因为:
- 显式的独立类型签名
type Function :: Obj Hask -> Obj Hask -> *强制GHC先完成Obj Hask的展开(替换为*),验证(->)的* -> * -> *kind是否符合要求。 - 当后续将
Arr Hask赋值为Function时,GHC只需要检查Function的kind是否匹配Arr t的要求——这一步已经在定义Function时完成,因此不会再触发kind不匹配的错误。
简单来说,独立类型签名相当于给GHC一个明确的信号,让它先完成类型族实例的展开和验证,而不是直接在类型族实例等式中进行未展开的kind对比。
内容的提问来源于stack exchange,提问作者rampion
相关产品推荐
相关产品推荐

