简体   繁体   中英

Using Just and Nothing Haskell

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:
App (Lambda "x" (Lambda "y" (Var "x"))) (Lambda "x" (Var "x")) App (Lambda "x" (Lambda "y" (Var "x"))) (Lambda "x" (Var "x"))
Just (Lambda "1_" (Lambda "x" (Var "x"))) Just (Lambda "1_" (Lambda "x" (Var "x")))
Another example:
Lambda "y" (Lambda "x" (Var "x")) Lambda "y" (Lambda "x" (Var "x"))
Nothing没有

As can be seen, the entire expression with only the one reduction performed is wrapped inside of the Just.

I will provide a few hints.

You need to perform the recursive calls, and check whether their result is Nothing or Just something . This part of your code looks OK:

appNF_OneStep (App e1 e2) =
    let f = appNF_OneStep e1
        a = appNF_OneStep e2
     in

Let's continue from there. There are four possible cases:

appNF_OneStep (App e1 e2) =
    let f = appNF_OneStep e1
        a = appNF_OneStep e2
    in case (f, a) of
       (Nothing, Nothing) -> ??? -- case 1
       (Nothing, Just a') -> ??? -- case 2
       (Just f', Nothing) -> ??? -- case 3
       (Just f', Just a') -> ??? -- case 4

In case 1, both e1 and e2 can not be reduced. Can we reduce their application? How?

In case 2, e1 can not be reduced, but e2 can (to a' ). Can we reduce their application? How?

And so on. You might not need to consider all four cases if you discover some of them are similar and can be grouped. Still, I'd recommend you start by examining all four cases, to understand what's going on.

The rest of the code has some issues:

appNF_OneStep::Expr -> Maybe Expr
appNF_OneStep (Var x) = (Var x)

Here the result (Var x) is an Expr , not a Maybe Expr , so it has the wrong type. We might fix that to Just (Var x) . Is that really the right result, though? Do we really have that a variable can make one reduction step resulting in itself?

Similarly,

appNF_OneStep (Lambda x ex) = (Lambda x (appNFOneStep ex))

returns the wrong type, Expr instead of Maybe Expr . On top of that, Lambda expects an Expr as second argument, but the recursive call is Maybe Expr , so that won't do. You need to proceed by cases, as for application:

appNF_OneStep (Lambda x ex) = case appNFOneStep ex of
   Nothing -> ???
   Just a  -> ???

Once you get fluent with Haskell, you could replace some of this boring code with helpers like fmap , but there is no need to hurry. Try to learn the basics of pattern matching and algebraic types, first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM