I'm trying to implement an interpreter for the lambda calculus that has constant intergers and supports the addition operation. The interpreter should use the call-by-value small-step operational semantics. So I've implemented a step that should be able to reduce a lambda term by one step. However, the stepper is losing the surrounding program of the reduced subterm when reduced.
This is my implementation in F#:
type Exp =
  | Cst of int
  | Var of string
  | Abs of string * Exp
  | App of Exp * Exp
  | Arith of Oper * Exp * Exp
and Oper =
  Plus
and the stepper looks like this:
let rec step (exp : Exp) (env : Map<string, Exp>) : Exp =
  match exp with
  | Cst _ | Abs(_) -> exp
  | Var x ->
    match Map.tryFind x env with
      | Some v -> v
      | None -> failwith "Unbound variable"
  | App(e1, e2) ->
    match step e1 env with
      | Abs(x, e) ->
        let newEnv = Map.add x (step e2 env) env
        step e newEnv
      | e1' -> failwithf "%A is not a lambda abstraction" e1'
  | Arith(Plus, Cst a, Cst b) -> Cst (a + b)
  | Arith(Plus, e1, Cst b) -> Arith(Plus, step e1 env, Cst b)
  | Arith(Plus, Cst a, e2) -> Arith(Plus, Cst a, step e2 env)
  | Arith(Plus, a, b) -> Arith(Plus, step a env, step b env)
So, given the following example of a program (\x.(\y.y x) 21 + 21) \x.x + 1
App
  (Abs
     ("x", App (Abs ("y", App (Var "y", Var "x")), Arith (Plus, Cst 21, Cst 21))),
   Abs ("x", Arith (Plus, Var "x", Cst 1)))
I expect the step function to only reduce the 21 + 21 while keeping the rest of the program i.e. I expect the following output after one step (\x.(\y.y x) 42) \x.x + 1. However, I'm not able to retain the surrounding code around the Cst 42. How should I modify the program such that it reduction only steps once while maintaining the rest of the program?
 
    