我刚刚开始使用Isabelle,我在Concrete Semantics的练习3.3中遇到类型统一错误:
定义替代函数
subst :: vname ⇒ aexp ⇒ aexp ⇒ aexp
这样
subst x a e
是x
中a
替换每个变量e
的结果。例如:subst ''x'' (N 3) (Plus (V ''x'') (V ''y'')) = Plus (N 3) (V ''y'')
这是我到目前为止所得到的:
theory Scratchpad
imports Main
begin
type_synonym vname = string
type_synonym val = int
type_synonym state = "vname ⇒ val"
datatype aexp = N int | V vname | Plus aexp aexp
fun subst :: "vname ⇒ aexp ⇒ aexp ⇒ aexp" where
"subst x (N a) (N e) = (N e)" |
"subst x (N a) (V e) = (if x=e then (N a) else (V e))" |
"subst x (N a) (Plus e1 e2) = Plus(subst(x (N a) e1) subst(x (N a) e2))"
end
当函数定义中的第三种情况被注释掉时,运行测试用例
value "subst ''x'' (N 3) (N 5)"
value "subst ''x'' (N 3) (V ''x'')"
分别生成(N 5)
和(N 3)
,所以我知道前两行正常工作。添加最后一行会导致错误
类型统一失败:类型“_⇒_”和“_ list”的冲突
应用程序中的类型错误:操作符不是函数类型
运营商:x :: char list
操作数:N a :: aexp
我不认为这是一个语法问题,虽然我还不完全确定不同类型的引号用于什么目的(例如双引号与两个单引号)。从this answer开始,我相信Isabelle正在将x
指定为该行右侧的函数类型,这不是我想要的。
错误消息的实际含义(具体而言一般),以及如何解决此问题?
答案 0 :(得分:4)
回答关于引号的问题:Isabelle / HOL中使用两个单引号(更确切地说是内部语法)来表示字符串文字。也就是说,''abc''
我们表示包含三个字符a
,b
和c
的字符串(如果你不得不按字面输入它们,它会再次使用一些特殊的语法)。另一方面,双引号主要用于将Isar语句(外部语法)与逻辑内的术语分开。因此,虽然''...''
是术语的一部分,但"..."
不是。
现在输入错误消息。它告诉您,您尝试使用列表x
(类型_ list
)作为函数(类型_ => _
)。为什么Isabelle认为您想使用x
作为函数?好吧,因为并置(即,彼此相邻地写条款,由空格分隔)表示功能应用。因此,x (N a)
被解释为将函数x
应用于参数(N a)
(正如f y
是f
对参数y
的应用)。为了给你的定义正确的含义,你必须在正确的位置使用括号。我猜你在第三个条款中的意图是:
Plus (subst x (N a) e1) (subst x (N a) e2)
我们将两次出现的函数subst
应用于三个参数。 (毕竟这是一个语法问题;)。)
另一个评论。您对subst
的实施可能更为一般。因此,subst
的第二个参数始终固定为某个数字a
(因为您使用了构造函数N
)。但是,如果允许使用aexp
类型的任意表达式,一切都应该正常工作。