I am implementing a lambda calculus interpreter and one of the functions I have to write is specified as follows. I have written all of the other functions but this one is really giving me trouble because it needs to return either Just Expr or Nothing and I'm not sure how to propogate this through the recursion:
A single step. Now write a function to do a single step of reduction:
appNF_OneStep :: Expr -> Maybe Expr
where the built-in Maybe type is defined as follows:
data Maybe a = Nothing | Just a
appNF_OneStep takes an expression e. If there is a redex available in e, it picks the correct applicative order redex and reduces e. (Note that in applicative order we are pursuing the leftmost, innermost strategy as follows. Pick the leftmost redex R; if there are nested (inner) redexes within R, pick the leftmost one, and so on, until we reach a redex without nested ones.) If a reduction was carried out, resulting in a new expression expr', appNF_OneStep returns Just expr', otherwise it returns Nothing.
As example inputs/outputs:
Input: App (Lambda "x" (Lambda "y" (Var "x"))) (Lambda "x" (Var "x"))
Correct Output: Just (Lambda "1_" (Lambda "x" (Var "x")))
Another example:
Input: Lambda "y" (Lambda "x" (Var "x"))
Correct Output: Nothing
As can be seen, the entire expression with only the one reduction performed is wrapped inside of the Just.