1

How do I use recursive function in Haskell?

I'm writing an evaluator for a little expression language, but I'm stuck on the Rec construct.

This is the language:

    data Expr = Var Nm  | Lam (Nm,Ty) Expr | App Expr Expr
          | Val Int | Add Expr Expr | If Expr Expr Expr
          | Rec Expr         

And this the evaluator so far:

    type Env = [ (Nm, Value) ]
    data Value = Clos Env Expr
               | Vint Int
           deriving Show
    ev :: Env -> Expr -> Value
    ev _   (Val n) = Vint n 
    ev env (Add e1 e2) = Vint (n1 + n2)  
       where
         Vint n1 = ev env e1  
         Vint n2 = ev env e2
    ev env (If e e1 e0) = if n==0 then ev env e0 else ev env e1
                              where 
                                Vint n = ev env e
    ev env (Var x) = case lookup x env of
                          Nothing -> error (x)
                          Just v  -> v
    ev env (Lam x e) = Clos env (Lam x e)
    ev env (App e1 e2) = case v1 of
                            Clos env1 (Lam (x,t) e) -> ev ((x,v2):env1) e
                              where
                                v1 = ev env e1
                                v2 = ev env e2

I would like to call the actual recursive function and execute it to get the sum from 1 to 100.

This is my test function I want to evaluate:

    t1 = Rec  (Lam ("f", INT :-> INT) . Lam ("i", INT) $
                If (Var "i")
                    (Var "i" `Add` (App (Var "f") (Var "i" `Add` Val(-1))))
                    (Var "i")
            )
    ev [] (App t1 (Val 100))

asnwer : Vint 5050

I've tried to make expression.

but,I got this error, ":(6,1)-(29,98): Non-exhaustive patterns in function ev"
I think there is a running error because the recursive function is not working properly.
Can you help me solve the problem?

4
  • 1
    Why do you think it's not correct? Commented Nov 27, 2020 at 2:32
  • 2
    Just to add to that a bit, this would greatly benefit from a Minimal Complete Example and being specific about eg the ghc error messages you get. It's good you have a clear code example but it's a fair way off minimal. As a result the question is over-general. Commented Nov 27, 2020 at 2:55
  • "<interactive>:(6,1)-(29,98): Non-exhaustive patterns in function eval", I got this error. Commented Nov 27, 2020 at 3:05
  • There is a running error because the recursive function is not working properly. Commented Nov 27, 2020 at 3:07

1 Answer 1

2

You might be looking for:

eval env (Rec (Lam (f,t) e)) = v
  where v = eval ((f,v):env) e

It's a little tricky. The idea is to close the body e of the Rec (Lam ...) construction in an environment that binds f to the value v of the returned closure itself. The easiest way to do it is using the recursive construction above, where the returned closure v references its own value in its context, lifting the recursive binding in your expression language to a recursive binding in Haskell.

Alternatively, if you don't want to use a recursive binding in the host language, there are other ways to do it. You can introduce a new value that represents a recursively bound closure:

data Value = ...
       | Loop Nm Value  -- this Value is a Clos
       ...

and then evaluating a Rec produces a Loop in place of the recursive binding:

eval env (Rec (Lam (f,t) e)) = Loop f (eval env e)

and you add a case to your App evaluator to handle the recursion:

eval env (App e1 e2) = case v1 of
  Loop f (Clos env1 (Lam (x,t) e)) -> eval ((x,v2):(f,v1):env1) e
  Clos env1 (Lam (x,t) e) -> eval ((x,v2):env1) e
  where
    v1 = eval env e1
    v2 = eval env e2

(I think I got that right. You might need to check some variable capture scenarios to be sure.)

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much.It helped me solve the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.