PureScript出现KindsDoNotUnify错误:跨模块类型别名推导Newtype实例失败
错误根本原因
这个错误是kind签名不匹配导致的,核心逻辑如下:
- 你给
TAlias显式声明的kind签名是forall k. k -> Type,表示它可以接收任意kind的类型参数。 - 但
TAlias的实现是将参数直接传给T,而在PureScript 0.14.x默认不开启PolyKinds扩展的前提下,你定义的T虽然写了forall m. m -> Type的kind签名,但实际编译器会将T的参数kind默认固定为Type,即T的实际有效kind是Type -> Type。 - 推导
Newtype实例时,编译器需要完全展开NewA的包装类型TAlias (M a)为T (M a),此时会触发全链路kind校验:TAlias要求参数是任意kindk,T要求参数是Type,两者无法统一,就抛出了KindsDoNotUnify错误。
解决方法
根据你的业务需求可选两种方案:
方案1:不需要多态kind(最常用,改动最小)
直接将TAlias和T的kind签名调整为匹配实际使用的Type -> Type即可,修改后模块B的代码如下:
module B where -- 调整T的kind签名为Type -> Type,和实际实现匹配 data T :: Type -> Type data T msg = E -- 调整TAlias的kind签名为Type -> Type,和T的签名对齐 type TAlias :: Type -> Type type TAlias msg = T msg
修改后重新编译即可正常推导Newtype实例。
方案2:需要支持多态kind
如果你的业务逻辑确实需要TAlias和T支持任意kind的参数,就在模块B的顶部开启PolyKinds扩展即可:
{-# LANGUAGE PolyKinds #-} module B where data T :: forall m. m -> Type data T msg = E type TAlias :: forall k. k -> Type type TAlias msg = T msg
开启扩展后编译器会支持多态kind,kind统一逻辑可以正常通过。
内容的提问来源于stack exchange,提问作者WHITECOLOR
相关产品推荐
相关产品推荐

