Emacs agda计划是否必须终止?

Emacs agda计划是否必须终止?,emacs,agda,halting-problem,Emacs,Agda,Halting Problem,在一些地方,所有agda计划都会终止。但是,我可以构造如下函数: stall : ∀ n → ℕ stall 0 = 0 stall x = stall x 语法highlighter似乎不喜欢它,但没有编译错误 计算stall 0的范式将导致0。计算失速1的结果会导致Emacs挂起,看起来很像一个非终止循环 这是虫子吗?或者Agda有时能永远运行吗?还是发生了更微妙的事情?您看到的语法突出显示是一个编译错误。终止检查器的效果是以一种粉红橙色(“三文鱼”)突出显示非终止函数。您可能会注意到,包

在一些地方,所有agda计划都会终止。但是,我可以构造如下函数:

stall : ∀ n → ℕ
stall 0 = 0
stall x = stall x
语法highlighter似乎不喜欢它,但没有编译错误

计算
stall 0
的范式将导致
0
。计算失速1的结果会导致Emacs挂起,看起来很像一个非终止循环


这是虫子吗?或者Agda有时能永远运行吗?还是发生了更微妙的事情?

您看到的语法突出显示是一个编译错误。终止检查器的效果是以一种粉红橙色(“三文鱼”)突出显示非终止函数。您可能会注意到,包含此类错误的模块无法从其他模块导入。它也不能被编译成Haskell


所以是的,Agda程序总是终止,这不是一个bug

事实上,存在编译错误。
agda
可执行文件发现一个错误,并将该信息传递到Emacs中的
agda模式
,该模式反过来进行语法高亮显示,让您知道有错误。我们可以看看如果直接使用
agda
会发生什么。这是我正在使用的文件:

module C1 where

open import Data.Nat

loop : ℕ → ℕ
loop 0 = 0
loop x = loop x
这确实是编译错误。此类错误阻止我们从其他模块导入或编译此模块。例如,如果我们将这些行添加到上面的文件中:

open import IO

main = run (putStrLn "")

其他类型的编译错误包括类型检查问题:

module C2 where

open import Data.Bool
open import Data.Nat

type-error : ℕ → Bool
type-error n = n
__________________________

D:\Agda\tc\C2.agda:7,16-17
ℕ !=< Bool of type Set

when checking that the expression n has type Bool
或未解决的元变量:

module C4 where

open import Data.Nat

meta : ∀ {a} → ℕ
meta = 0
__________________________

Unsolved metas at the following locations:
  D:\Agda\tc\C4.agda:5,11-12
现在,要检查
refl
是否是该类型的正确表达式,
agda
必须计算
循环1
。但是,由于终止检查失败,
agda
将不会展开
循环
(并以无限循环结束)

然而,
C-C-n
确实迫使
agda
尝试对表达式求值(你基本上告诉它“我知道我在做什么”),所以你自然会进入一个无限循环


顺便说一句,如果禁用终止检查,则可以执行
agda
循环:

{-# NO_TERMINATION_CHECK #-}
loop : ℕ → ℕ
loop 0 = 0
loop x = loop x

data _≡_ {a} {A : Set a} (x : A) : A → Set a where
  refl : x ≡ x

test : loop 1 ≡ 1
test = refl
结果是:

stack overflow

根据经验:如果您可以通过检查(或编译)模块而不使用任何编译器pragmas来使
agda
循环,那么这确实是一个bug,应该在上报告。这就是说,如果您愿意使用编译器pragmas,则很少有方法可以生成非终止程序。我们已经看到了
{-#NO#u TERMINATION_CHECK}
,下面是一些其他方法:

{-# OPTIONS --no-positivity-check #-}
module Boom where

data Bad (A : Set) : Set where
  bad : (Bad A → A) → Bad A

unBad : {A : Set} → Bad A → Bad A → A
unBad (bad f) = f

fix : {A : Set} → (A → A) → A
fix f = (λ x → f (unBad x x)) (bad λ x → f (unBad x x))

loop : {A : Set} → A
loop = fix λ x → x
这个依赖于严格意义上不是正的数据类型。或者我们可以强制
agda
接受
Set:Set
(即
Set
的类型是
Set
本身)并重构:

不过,这真是一团糟。但它有一个很好的特性,即它只使用依赖函数。奇怪的是,它甚至没有通过类型检查,导致
agda
循环。将整个
循环
术语拆分为两个帮助

data _≡_ {a} {A : Set a} (x : A) : A → Set a where
  refl : x ≡ x

test : loop 1 ≡ 1
test = refl
{-# NO_TERMINATION_CHECK #-}
loop : ℕ → ℕ
loop 0 = 0
loop x = loop x

data _≡_ {a} {A : Set a} (x : A) : A → Set a where
  refl : x ≡ x

test : loop 1 ≡ 1
test = refl
stack overflow
{-# OPTIONS --no-positivity-check #-}
module Boom where

data Bad (A : Set) : Set where
  bad : (Bad A → A) → Bad A

unBad : {A : Set} → Bad A → Bad A → A
unBad (bad f) = f

fix : {A : Set} → (A → A) → A
fix f = (λ x → f (unBad x x)) (bad λ x → f (unBad x x))

loop : {A : Set} → A
loop = fix λ x → x
{-# OPTIONS --type-in-type #-}
module Boom where

open import Data.Empty
open import Data.Product
open import Relation.Binary.PropositionalEquality

data M : Set where
  m : (I : Set) → (I → M) → M

_∈_ : M → M → Set
a ∈ m I f = Σ I λ i → a ≡ f i

_∉_ : M → M → Set
a ∉ b = (a ∈ b) → ⊥

-- Set of all sets that are not members of themselves.
R : M
R = m (Σ M λ a → a ∉ a) proj₁

-- If a set belongs to R, it does not contain itself.
lem₁ : ∀ {X} → X ∈ R → X ∉ X
lem₁ ((Y , Y∉Y) , refl) = Y∉Y

-- If a set does not contain itself, then it is in R.
lem₂ : ∀ {X} → X ∉ X → X ∈ R
lem₂ X∉X = (_ , X∉X) , refl

-- R does not contain itself.
lem₃ : R ∉ R
lem₃ R∈R = lem₁ R∈R R∈R

-- But R also contains itself - a paradox.
lem₄ : R ∈ R
lem₄ = lem₂ lem₃

loop : {A : Set} → A
loop = ⊥-elim (lem₃ lem₄)
{-# OPTIONS --type-in-type #-}
module Boom where

⊥   = ∀ p → p
¬_  = λ A → A → ⊥
℘_  = λ A → A → Set
℘℘_ = λ A → ℘ ℘ A

U = (X : Set) → (℘℘ X → X) → ℘℘ X

τ : ℘℘ U → U
τ t = λ (X : Set) (f : ℘℘ X → X) (p : ℘ X) → t λ (x : U) → p (f (x X f))

σ : U → ℘℘ U
σ s = s U λ (t : ℘℘ U) → τ t

τσ : U → U
τσ x = τ (σ x)

Δ = λ (y : U) → ¬ (∀ (p : ℘ U) → σ y p → p (τσ y))
Ω = τ λ (p : ℘ U) → ∀ (x : U) → σ x p → p x

loop : (A : Set) → A
loop = (λ (₀ : ∀ (p : ℘ U) → (∀ (x : U) → σ x p → p x) → p Ω) →
  (₀ Δ λ (x : U) (₂ : σ x Δ) (₃ : ∀ (p : ℘ U) → σ x p → p (τσ x)) →
  (₃ Δ ₂ λ (p : ℘ U) → (₃ λ (y : U) → p (τσ y)))) λ (p : ℘ U) →
  ₀ λ (y : U) → p (τσ y)) λ (p : ℘ U) (₁ : ∀ (x : U) → σ x p → p x) →
  ₁ Ω λ (x : U) → ₁ (τσ x)