使用函数编码属性的缺点是什么?

时间:2018-09-06 03:41:14

标签: agda

在阿格达(Agda)中,似乎经常有两种方法来完善一套。一种是通过简单地编写一个检查属性是否成立并提升的函数。例如:

has_true : List Bool -> Bool 
has_true (true ∷ xs) = true
has_true (false ∷ xs) = has_true xs
has_true [] = false

Truthy : List Bool -> Set
Truthy list = T (has_true list)

在这里,Truthy list证明布尔列表至少具有一个真实元素。另一种方法是直接将该属性编码为归纳类型:

data Truthy : List Bool -> Set where
  Here  : (x : Bool) -> (x ≡ true) -> (xs : List Bool) -> Truthy (x ∷ xs)
  There : (x : Bool) -> (xs : List Bool) -> Truthy xs -> Truthy (x ∷ xs)

在这里,Truthy list也是一样。

我相信我之前已经阅读过一个比较,但我不记得了。这些不同的样式有名称吗?使用一种样式优于另一种样式有什么优点和缺点?还有第三种选择吗?

1 个答案:

答案 0 :(得分:6)

到目前为止,您列出了两种定义谓词的方法:

  1. A -> Bool函数。
  2. 归纳谓词。

我还要再添加一个:

  1. A -> Set函数。也可以称为“递归定义”或“通过大消除定义”。

第三个版本是Agda中的以下版本:

open import Data.Bool
open import Data.Unit
open import Data.Empty
open import Data.List

hastrue : List Bool → Set
hastrue []           = ⊥   -- empty type
hastrue (false ∷ bs) = hastrue bs
hastrue (true ∷ bs)  = ⊤   -- unit type

首先,让我们谈谈使用这三个选项的哪种谓词可表示。这是一个ASCII表。 *是通配符,表示是/否。

                    | P : A -> Set | P : A -> Bool | data P : A -> Set |
|-------------------|--------------|---------------|-------------------|
| Proof irrelevant  | *            | yes           | *                 |
| Structural        | yes          | yes           | *                 |
| Strictly positive | *            | N/A           | yes               |
| Decidable         | *            | yes           | *                 |

证明不相关表示P x的所有证明都是相同的。在Bool情况下,证明通常是一些p : P x ≡ truep : IsTrue (P x)IsTrue = λ b → if b then ⊤ else ⊥,并且在两种情况下,所有证明确实相等。我们可能希望也可能不希望谓词不相关。

结构表示P x只能使用结构上小于A的{​​{1}}元素来定义。函数始终是结构性的,因此,如果某些谓词不是结构性的,则只能归纳定义。

严格肯定的表示x不能递归出现在功能箭头的左侧。非严格的肯定谓词不能归纳定义。与证明相关的非严格正谓词的一个示例是对功能类型的代码的解释:

P

判定是不言自明的; data Ty : Set where top : Ty fun : Ty → Ty → Ty ⟦_⟧ : Ty → Set ⟦ top ⟧ = ⊤ ⟦ fun A B ⟧ = ⟦ A ⟧ → ⟦ B ⟧ -- you can't put this in "data" 函数必须是可判定的,这使它们不适用于不可判定的谓词或不能轻易地作为结构性A -> Bool函数写出来的谓词。可判定性的优点是排除了中间推理,而没有假设或其他可判定性证明的非Bool谓词定义是不可能的。

第二,关于 Agda / Idris中的实际后果

  • 您可以对归纳谓词的证明进行从属模式匹配。使用递归和布尔谓词,您必须首先对Bool值进行模式匹配,以使谓词见证计算。有时,这使归纳谓词变得方便,例如。您可能有一个包含10个构造函数的枚举类型,并且您希望谓词仅包含一个构造函数。归纳定义的谓词只允许您匹配真实情况,而其他版本则要求您始终匹配所有情况。

  • 另一方面,布尔值和递归谓词会在您知道A元素具有给定形状后自动进行计算。可以在Agda中使用它来使类型推断自动填充证明,而无需使用战术或实例。例如,只要A是带有已知的hastrue xs前缀的列表表达式,就可以通过对对和单位类型的eta规则来解决类型为xs的空洞或隐式参数。类似于布尔谓词。