事实上,试图在trustMe
上进行模式匹配时,如果不匹配refl
,则会导致卡住的术语。也许正是启发看到(的一部分),它定义后面trustMe
原始操作的代码,primTrustMe
:
(u', v') <- normalise (u, v)
if (u' == v') then redReturn (refl $ unArg u) else
return (NoReduction $ map notReduced [a, t, u, v])
这里,u
和v
代表术语x
和y
,分别。代码的其余部分可以在模块Agda.TypeChecking.Primitive
中找到。
所以,是的,如果x
和y
不definitionally相等,则primTrustMe
(通过扩展trustMe
)表现为在这个意义上,评价只是卡住一个假设。然而,将Agda编译为Haskell时有一个关键的区别。纵观在模块Agda.Compiler.MAlonzo.Primitives
,我们发现这样的代码:
("primTrustMe" , Right <$> do
refl <- primRefl
flip runReaderT 0 $
term $ lam "a" (lam "A" (lam "x" (lam "y" refl))))
这看起来可疑:它总是返回refl
无论什么x
和y
是。让我们来测试模块:
module DontTrustMe where
open import Data.Nat
open import Data.String
open import Function
open import IO
open import Relation.Binary.PropositionalEquality
open import Relation.Binary.PropositionalEquality.TrustMe
postulate
trustMe′ : ∀ {a} {A : Set a} {x y : A} → x ≡ y
transport : ℕ → String
transport = subst id (trustMe {x = ℕ} {y = String})
main = run ∘ putStrLn $ transport 42
使用trustMe
内transport
,编译模块(C-c C-x C-c
)和运行生成的可执行文件,我们可以得到......你猜对了正确的 - 段错误。
如果我们转而使用假设,我们最终得到:
DontTrustMe.exe: MAlonzo Runtime Error:
postulate evaluated: DontTrustMe.trustMe′
如果您不打算编译程序(在使用MAlonzo至少),那么矛盾应该是你唯一担心的(上另一方面,如果你只是检查你的程序,那么不一致通常是一件大事)。
我现在可以考虑两种用例,首先是(如你所说)实现基元。标准库在以下三个地方使用trustMe
:执行Name
s(Reflection
模块),String
s(Data.String
模块)和Char
s(Data.Char
模块)的可判定等值。
第二个与第一个非常相似,不同之处在于您自己提供数据类型和相等函数,然后使用trustMe
跳过证明并仅使用相等函数来定义可判定的相等性。例如:
open import Data.Bool
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
data X : Set where
a b : X
eq : X → X → Bool
eq a a = true
eq b b = true
eq _ _ = false
dec-eq : Decidable {A = X} _≡_
dec-eq x y with eq x y
... | true = yes trustMe
... | false = no whatever
where postulate whatever : _
但是,如果你搞砸了eq
,编译器不能保存你。