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

Haskell使用singletons包时为已有类型添加Typeclass约束的方案咨询

解决方案

你不需要重定义singletons库的核心类型与函数,只需要将「所有SType对应的类型都具备Typeable实例」这一事实告知编译器即可,有两种常用实现方式:

方式1:无额外依赖实现

直接写一个高阶辅助函数封装约束传递逻辑:

-- 给SType添加约束携带辅助函数
withSTypeTypeable :: SType a -> (Typeable a => r) -> r
withSTypeTypeable SInteger f = f
withSTypeTypeable SBoolean f = f
withSTypeTypeable SByteStr f = f

-- 修改checkResult实现,调用辅助函数引入Typeable约束
checkResult :: EType -> UntypedExp -> Maybe Result
checkResult typ expr = withSomeSing typ $ \singType ->
  withSTypeTypeable singType $
    makeResult singType <$> inferExpr expr

每个分支匹配到具体的SType构造器时,对应的a类型是确定的,Typeable实例天然存在,编译器会自动识别该约束并允许调用inferExpr。

方式2:使用constraints包简化写法

如果你的项目已经依赖了constraints包,可以用Dict更简洁地实现约束传递:

import Data.Constraint (Dict(..))

sTypeHasTypeable :: SType a -> Dict (Typeable a)
sTypeHasTypeable SInteger = Dict
sTypeHasTypeable SBoolean = Dict
sTypeHasTypeable SByteStr = Dict

checkResult :: EType -> UntypedExp -> Maybe Result
checkResult typ expr = withSomeSing typ $ \singType ->
  case sTypeHasTypeable singType of
    Dict -> makeResult singType <$> inferExpr expr

模式匹配到Dict时,Typeable a约束会自动进入作用域,后续调用inferExpr就不会报错。

方案优势

对比你当前自定义SomeSing、SingKind的临时方案,该方案有几个明显好处:

  • 不需要隐藏singletons库的核心定义,后续库版本升级不会出现兼容问题
  • 不需要修改SingKind的泛用实现,仅针对你自定义的SType添加少量辅助代码即可
  • 逻辑更清晰,明确限定只有SType对应的类型才携带Typeable约束,不会破坏singletons原有功能的泛用性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 02:30:01