我定义了以下功能:
fun count:: "'a ⇒ 'a list ⇒ nat" where
"count a Nil = 0" |
"count a (Cons b xs) = (count a xs)" |
"count a (Cons a xs) = (count a xs) + (Suc 0)"
它应该计算与a相同类型的元素的列表中元素a的出现次数。我收到以下错误:
Malformed definition:
Nonlinear patterns not allowed in sequential mode.
⋀a xs. count a (a # xs) = count a xs + Suc 0
答案 0 :(得分:4)
关于模式,“线性”表示每个自由变量仅一次出现。在第三行中,左侧的图案包含两次a
,这使其变为非线性。功能包的“顺序”模式不支持此功能。在这种模式下,您可以一个接一个地指定可能重叠的函数方程,而第一个匹配的方程就是计数。这也是“ fun”命令使用的模式,也是Haskell之类的函数式编程语言通常采用的模式(请注意,它们通常也不允许使用非线性模式)。
这里基本上有两种可能:如果您绝对要使用非线性模式,则可以编写
function count:: "'a ⇒ 'a list ⇒ nat" where
"count a Nil = 0"
| "a ≠ b ⟹ count a (Cons b xs) = (count a xs)"
| "count a (Cons a xs) = (count a xs) + (Suc 0)"
by (metis neq_Nil_conv surj_pair) auto
termination by lexicographic_order
请注意,您必须显示出这样的事实,即模式是穷举性的,并且不手动终止。 “趣味”功能不那么强大,但会自动执行所有这些操作。
一种更容易和更好的方法是,以一种更适合系统自动化的方式重新定义您的定义:
fun count:: "'a ⇒ 'a list ⇒ nat" where
"count a Nil = 0"
| "count a (Cons b xs) = (count a xs) + (if a = b then 1 else 0)‹›
出于各种原因(更短,更容易,在代码生成中更有效),这几乎总是可取的。
有关功能包的更多信息,请咨询documentation。这是一个功能强大且用途广泛的工具,但是如果您仅凭“乐趣”就能得到想要的东西,那通常就是您想要的方式。