我在Haskell中找到了关于等式推理和证明的练习。提供以下代码:
type Stack = [Int]
type Code = [Op]
data Op = PUSH Int | ADD
deriving (Show)
--
-- Stack machine
--
exec :: Code -> Stack -> Stack
exec [ ] s = s
exec (PUSH n : c) s = exec c (n:s)
exec (ADD:c) (m:n:s) = exec c (n+m : s)
--
-- Interpeter
--
data Expr = Val Int | Add Expr Expr
deriving (Show)
eval :: Expr -> Int
eval (Val n) = n
eval (Add x y) = eval x+eval y
--
-- Compiler
--
comp :: Expr -> Code
comp (Val n) = [PUSH n]
comp (Add x y) = comp x ++ comp y ++ [ADD]
现在我必须证明exec(comp e) s = eval e : s
。
所以到目前为止我找到了这个答案:
我们必须证明exec (comp e) s = eval e : s
。
第一种情况:假设e = (Val n)
。然后是comp (Val n) = [PUSH n]
,所以我们必须证明exec ([PUSH n]) s = eval ([PUSH n] : s)
。我们使用exec的函数定义找到exec ([PUSH n]) s = exec [] (n:s) = (n:s)
。
现在eval (Val n) : s = n : s
。第一种情况还可以!
第二种情况:假设e = (Add x y)
。然后是comp (Add x y) = comp x ++ comp y ++ [ADD]
。
但现在我正在努力使用comp的递归使用。我应该在这些树上使用某种形式的树木和感应来证明这一点吗?我不完全确定如何做到这一点。
答案 0 :(得分:2)
当exec
的第一个参数是一个列表时,两种可能性是:
exec (PUSH n: codes) -- #1
exec (ADD : codes) -- #2
在归纳步骤中,您可以假设命题适用于codes
,即您可以假设:
exec codes s = eval codes : s
s 的任何值 - 记住这一点 - 这通常是任何入门证明的关键步骤。
首先使用您为exec
编写的代码扩展#1:
exec (PUSH n: codes) s == exec codes (n:s)
== ...
== ...
== eval (PUSH n: codes) : s
你能看到一个使用归纳假设的地方吗?