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

Idris编译器能否隐式查找证明?及带证明的字典取值函数问题

嗨,我来帮你搞定这个Idris依赖类型编程的问题,正好在这类场景上有不少实践经验~

一、实现带键存在证明的字典检索函数

首先先补全你没贴的基础定义(应该和你想的差不多),先定义字典类型和键存在的证明谓词:

-- 字典类型:schema是(String, Type)的列表,描述每个键对应的类型
data Dict : List (String, Type) -> Type where
  Empty : Dict []
  Insert : (key : String) -> (val : ty) -> Dict rest -> Dict ((key, ty) :: rest)

-- 证明某个键存在于schema中的谓词
data HasKey : String -> List (String, Type) -> Type where
  Here : HasKey key ((key, ty) :: rest)  -- 键在当前列表头部
  There : HasKey key rest -> HasKey key ((other, ty) :: rest)  -- 键在列表剩余部分

接下来就可以写安全的检索函数了,把HasKey作为参数,确保调用时键一定存在:

lookup : (key : String) -> (dict : Dict schema) -> HasKey key schema -> ty
lookup key (Insert key val rest) Here = val
lookup key (Insert other val rest) (There prf) = lookup key rest prf

这里Idris会自动根据HasKey的证明推断出返回值的ty,完全保证类型安全。

二、关于Idris自动查找证明的问题

答案是当然可以,但需要借助Idris的自动隐式机制,具体可以这么做:

1. 把证明设为自动隐式参数

修改lookup函数,用{auto prf : ...}把证明参数标记为自动推导:

lookup : (key : String) -> (dict : Dict schema) -> {auto prf : HasKey key schema} -> ty
lookup key (Insert key val rest) {prf = Here} = val
lookup key (Insert other val rest) {prf = There prf} = lookup key rest

现在调用的时候,只要编译器能通过上下文推断出键确实存在,就不用手动传证明了。比如你构造了一个带"name"键的字典:

myDict : Dict [("name", String), ("age", Nat)]
myDict = Insert "name" "Alice" (Insert "age" 30 Empty)

直接调用lookup "name" myDict,编译器会自动找到Here的证明;调用lookup "age" myDict,会自动找到There Here的证明,完全不用你手动写。

2. 复杂场景下的自动证明

如果键的存在不是静态可推断的(比如依赖运行时输入),编译器没办法自动构造证明,这时候可以写一个可判定性函数,让编译器在运行时判断键是否存在:

-- 判定某个键是否存在于schema中,返回Dec(可判定结果)
decHasKey : (key : String) -> (schema : List (String, Type)) -> Dec (HasKey key schema)
decHasKey key [] = No (\prf => case prf of {})  -- 空列表肯定不存在
decHasKey key ((k, ty) :: rest) =
  if key == k
    then Yes Here  -- 当前键匹配,返回存在证明
    else case decHasKey key rest of
           Yes prf => Yes (There prf)  -- 剩余部分存在,包装成There证明
           No contra => No (\Here => contra Here; (There prf) => contra prf)  -- 剩余部分不存在,构造否定证明

有了这个函数,你就可以在运行时处理不确定的键,比如:

handleLookup : String -> Dict schema -> Maybe ty
handleLookup key dict =
  case decHasKey key schema of
    Yes prf => Just (lookup key dict prf)
    No _ => Nothing

总的来说,Idris的自动证明查找对简单的静态场景非常友好,复杂场景则需要你提供可判定性函数来辅助编译器。

内容的提问来源于stack exchange,提问作者Rafael S. Calsaverini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:09:04