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

为何无法在Agda中定义Set→Set类型函数?如何实现类Haskell闭类型族映射?

如何在Agda中实现类似Haskell封闭类型族的类型映射?

首先定义四个基础类型:

data Q : Set where
  q1 : Q
  q2 : Q

data P : Set where
  p1 : P
  p2 : P

data C : Set where
  c1 : C
  c2 : C

data D : Set where 
  d1 : D 
  d2 : D

当尝试定义如下函数时,会触发unreachable clause警告:

f : Set -> Set
f D = Q
f P = C

这是因为Agda要求Set -> Set类型的函数必须覆盖所有Set类型的输入,但我们只需要指定D、P到Q、C的映射,这和Haskell封闭类型族的需求一致,以下是两种可行的实现方式:

方法1:基于索引数据类型的类型家族

通过定义一个枚举目标类型的索引类型,再基于该索引实现类型映射,完全符合Agda的函数完备性要求:

-- 枚举需要参与映射的类型标识
data TargetType : Set where
  DT : TargetType
  PT : TargetType

-- 将标识映射到实际的Set类型
TypeOf : TargetType -> Set
TypeOf DT = D
TypeOf PT = P

-- 定义目标类型映射,对应Haskell的封闭类型族
F : TargetType -> Set
F DT = Q
F PT = C

使用时,F DT会得到Q,F PT会得到C。如果需要扩展映射关系,只需给TargetType添加新构造子,并补全TypeOf和F的定义即可,和封闭类型族的扩展性逻辑一致。

方法2:利用Agda实例系统实现

如果希望更贴近Haskell类型族的使用体验,可以借助Agda的实例系统来实现:

-- 定义记录类型,描述两个类型的映射关系
record TypeMap (A B : Set) : Set where
  constructor mkTypeMap

-- 为需要的类型对定义实例
instance
  dToQ : TypeMap D Q
  dToQ = mkTypeMap

  pToC : TypeMap P C
  pToC = mkTypeMap

-- 通过实例查找自动推导映射后的类型
F : Set -> Set
F A = {B : Set} {{_ : TypeMap A B}} -> B

使用时,只要存在对应的TypeMap实例,F D会自动推导为Q,F P会推导为C。若传入没有对应实例的类型,Agda会直接报错,这和Haskell封闭类型族未覆盖类型时的行为一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 00:09:22