在Haskell / Idris中打开类型级别证明

时间:2014-11-30 23:40:34

标签: haskell proof category-theory correctness idris

在Idris / Haskell中,人们可以通过注释类型和使用GADT构造函数来证明数据的属性,例如使用Vect,但是,这需要将属性硬编码到类型中(例如,Vect必须是与类型不同的类型)列表)。 是否可以使用具有开放属性集的类型(例如包含长度和运行平均值的列表),例如通过重载构造函数或使用效果的静脉内的东西?

1 个答案:

答案 0 :(得分:17)

我相信麦克布莱德已经在他的ornament paper (pdf)中回答了这个问题(对于类型理论)。你正在寻找的概念是一个代数装饰(强调我的):

  

代数φ描述了解释数据的结构方法   上升到折叠φ操作,递归地应用该方法。   不出所料,φ的调用树具有相同的结构   结构作为原始数据 - 毕竟是重点。但   如果那是最重要的话呢?假设我们想修复   预先折叠φ的结果,仅代表那些数据   提供我们想要的答案。我们应该需要数据来适应   φ呼叫的树,它提供了答案。 我们可以限制我们的数据吗?   那到底是什么?如果我们按答案索引,我们当然可以。

现在,让我们写一些代码。我把整个事情in a gist放了,因为我要在这里插入评论。另外,我正在使用Agda,但它应该很容易转换为Idris。

module reornament where

我们首先定义代表B代表A代数的代数意味着什么。我们需要一个基本案例(类型B的值)以及将列表的头部与归纳假设结合起来的方法。

ListAlg : (A B : Set) → Set
ListAlg A B = B × (A → B → B)

根据这个定义,我们可以定义由A索引的B列表的类型,其值恰好是对应于给定ListAlg A B的计算结果。在nil的情况下,结果是代数(proj₁ alg)提供给我们的基本情况,而在cons情况下,我们简单地将归纳假设与新的头部结合起来使用第二次预测:

data ListSpec (A : Set) {B : Set} (alg : ListAlg A B) : (b : B) → Set where
  nil  :  ListSpec A alg (proj₁ alg)
  cons : (a : A) {b : B} (as : ListSpec A alg b) → ListSpec A alg (proj₂ alg a b)

好的,让我们导入一些库,现在看几个例子:

open import Data.Product
open import Data.Nat
open import Data.List

计算列表长度的代数由0作为基本情况给出,const suc作为组合A和尾部长度以构建长度的方式目前的清单。因此:

AlgLength : {A : Set} → ListAlg A ℕ
AlgLength = 0 , (λ _ → suc)

如果元素是自然数,那么它们可以求和。与之对应的代数具有0作为基本情况,_+_作为将与尾部中包含的元素的总和组合在一起的方式。因此:

AlgSum : ListAlg ℕ ℕ
AlgSum = 0 , _+_

疯狂的想法:如果我们有两个代数在相同的元素上工作,我们可以将它们组合起来!这样我们就会跟踪2个不变量而不是1个!

Alg× : {A B C : Set} (algB : ListAlg A B) (algC : ListAlg A C) →
       ListAlg A (B × C)
Alg× (b , sucB) (c , sucC) = (b , c) , (λ a → λ { (b , c) → sucB a b , sucC a c })

现在举例:

如果我们跟踪长度,那么我们可以定义向量:

Vec : (A : Set) (n : ℕ) → Set
Vec A n = ListSpec A AlgLength n

并且,例如,这个长度为4的向量:

allFin4 : Vec ℕ 4
allFin4 = cons 0 (cons 1 (cons 2 (cons 3 nil)))

如果我们跟踪元素的总和,那么我们可以定义分布的概念:统计分布是总和为100的概率列表:

Distribution : Set
Distribution = ListSpec ℕ AlgSum 100

我们可以定义一个统一的例子:

uniform : Distribution
uniform = cons 25 (cons 25 (cons 25 (cons 25 nil)))

最后,通过结合长度和和代数,我们可以实现大小分布的概念。

SizedDistribution : ℕ → Set
SizedDistribution n = ListSpec ℕ (Alg× AlgLength AlgSum) (n , 100)

为4个元素集提供这个漂亮的均匀分布:

uniform4 : SizedDistribution 4
uniform4 = cons 25 (cons 25 (cons 25 (cons 25 nil)))