Я нашел это упражнение по эквациональным рассуждениям и доказательствам в 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 ([PUSH n]) s = exec [] (n:s) = (n:s) используя определение функции exec.
Теперь eval (Val n) : s = n : s. Первый случай в порядке!
Второй случай: Предположим, e = (Add x y). Затем comp (Add x y) = comp x ++ comp y ++ [ADD].
Но теперь я борюсь с этим рекурсивным использованием comp. Должен ли я использовать какую-то форму деревьев и индукцию по этим деревьям, чтобы доказать это? Я не совсем уверен, как это сделать.
exec _ [] = error "ADD applied to an empty or singleton stack"- person epsilonhalbe   schedule 31.05.2016exec— в частности, у вас естьexec (a ++ b) s = exec b (exec a s). Это позволит вам написатьexec (comp x ++ comp y ++ [ADD])какexec [ADD] (exec (comp y) (exec (comp x)))- person user2407038   schedule 31.05.2016