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

如何为Haskell异构集合的所有元素应用统一类型约束并实现映射

1 报错原因解释

  • 第一种实现的报错:
    你写的普通函数签名仅声明了AllConstrained c types约束,但GHC无法仅凭类型族约束自动对类型级列表types做递归分发处理,要遍历异构列表必须依赖类型类实例的模式匹配。另外你签名里的约束c和高阶函数参数内部forall量化的约束c属于不同作用域,GHC无法判定二者是同一个变量,因此会生成未确定的类型变量c0抛出无法推导的错误。
  • 第二种实现的报错:
    你把AllConstrained c types约束放到了类型类方法的签名里,而不是实例上下文中,属于多余声明。且直接传入ContraintRunnerF show时,约束参数c没有被显式指定,GHC的类型推断不会反向匹配后续HTypeMap元素的约束来确定c的具体值,因此会抛出c0不确定的错误。

2 通用映射函数实现

首先你需要开启以下GHC扩展:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE RankNTypes #-}

你不需要额外的ContraintRunnerF包装,直接把约束放到类型类实例的上下文即可:

import Prelude hiding (map)

data HTypeMap (f :: * -> *) (types :: [*]) where
  HNil :: HTypeMap f '[]
  HCons :: f e -> HTypeMap f types -> HTypeMap f (e ': types)

class MapConstrained (c :: * -> Constraint) (types :: [*]) where
  mapConstrained :: forall f r. (forall t. c t => f t -> r) -> HTypeMap f types -> [r]

instance MapConstrained c '[] where
  mapConstrained _ HNil = []

instance (c t, MapConstrained c ts) => MapConstrained c (t ': ts) where
  mapConstrained f (HCons e rest) = f e : mapConstrained @c f rest

你期望的showEverything可以直接实现:

showEverything :: MapConstrained Show types => HTypeMap f types -> [String]
showEverything = mapConstrained @Show show

测试用例可以直接运行,不需要显式包装高阶参数:

testMap :: HTypeMap Maybe '[Int, String]
testMap = HCons (Just 3) (HCons (Just "Hello") HNil)

test2 :: [String]
test2 = mapConstrained @Show show testMap
-- 运行结果: ["Just 3","Just \"Hello\""]

如果要兼容你最开始定义的AllConstrained类型族,只需要加一行等价约束映射即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:42:01