如何使用等式推理证明这个Haskell代码

时间:2016-05-31 14:23:28

标签: haskell recursion proof equational-reasoning

我在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的递归使用。我应该在这些树上使用某种形式的树木和感应来证明这一点吗?我不完全确定如何做到这一点。

1 个答案:

答案 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

你能看到一个使用归纳假设的地方吗?