You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何PureScript无法推断Row.Cons约束?新类型使用疑惑

PureScript新类型约束推断失败问题

代码背景

首先定义了一个带参数化类型的新类型:

newtype MockState m = MockState { apiState :: {api1 :: m Int, api2:: m String} }
derive instance newtypeMockState :: Newtype (MockState m) _

随后编写了从字段创建Ref的函数版本1:

createRef :: forall s a b r r' rem 
        .  IsSymbol s
        => Newtype (MockState Identity) {apiState :: Record r}
        => Row.Cons s (Identity a) r' r 
        => Proxy s 
        -> MockState Identity
        -> Effect (Ref.Ref a)
createRef pxy (MockState mockState)= do 
      let (Identity val) = Record.get pxy mockState.apiState
      Ref.new val

这个版本编译报错,提示找不到Row.Cons实例:

No type class instance was found for

Prim.Row.Cons s4
              (Identity a5)
              t2
              ( cla :: Identity String
              , login :: Identity Int
              )

直接传入Record r而非新类型时编译正常,且以下版本可以正常工作:

createRef :: forall s a b mock r' r rem 
        .  IsSymbol s
        => Newtype mock {apiState :: Record r}
        => Row.Cons s (Identity a) r' r 
        => Proxy s 
        -> mock
        -> Effect (Ref.Ref a)
createRef pxy r = do 
      let (Identity val) = Record.get pxy (unwrap r).apiState
      Ref.new val

问题原因

两个版本逻辑看似一致,但第一个版本编译失败的核心是编译器缺少足够的类型推断线索:

  • 第一个版本直接把约束绑定到具体的MockState Identity类型上,但Newtype (MockState Identity) {apiState :: Record r}这个约束没有明确建立起MockState Identity内部字段结构和Record r的关联。编译器无法自动将MockState定义里的{api1 :: Identity Int, api2 :: Identity String}和约束中的Record r划等号,自然找不到对应的Row.Cons实例。
  • 第二个版本使用泛型的mock类型变量,再通过unwrap显式提取新类型的内部值,相当于给编译器明确了关联路径:从mock中unwrap得到的结构,其apiState就是Record r,这样编译器能顺利将行类型与Row.Cons约束匹配,完成类型推断。

内容的提问来源于stack exchange,提问作者Saravanan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:55:28