Emacs agda计划是否必须终止?
在一些地方,所有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有时能永远运行吗?还是发生了更微妙的事情?您看到的语法突出显示是一个编译错误。终止检查器的效果是以一种粉红橙色(“三文鱼”)突出显示非终止函数。您可能会注意到,包
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)