1

Could anybody tell me why the following code in Haskell is not working?

a = 5
foo :: Int -> Int -> Int
foo a 0 = 0
foo a b = a + foo a (b - 1)
  where
    a = a + 1
4
  • It doesn't work because the a in a+1 refers to the a defined on that same line, so the definition is infinitely recursive. But which a do you want it to refer to? The parameter of foo or the one defined on line 1? Why do you have so many variables named a? What is the code meant to do? Is it just an experiment on how scope works? Commented Nov 12, 2018 at 22:51
  • It's just an experiment. I have a more complex problem and I reduced it at this simple. It's about adding 2 binary numbers using 2 functions: one for the actual sum and one for carry bit. I don't know how to transfer the value of the carry bit to the next step of the recursion Commented Nov 12, 2018 at 22:55
  • Okay, so how do you want the scope to work out. Like, what's your desired result here - which a do you want to refer to which definition? Do you want it to be the same as foo a b = (a + 1) + foo (a + 1) (b - 1) or something else? Commented Nov 12, 2018 at 22:59
  • Yes, that's exactly what I want the function to do Commented Nov 12, 2018 at 23:03

1 Answer 1

4

In Haskell a variable is in scope during its definition, so in a = a + 1, the a is referring to itself. If we rename the variables in your code, so that all variables have unique names, it will look like this:

a1 = 5
foo :: Int -> Int -> Int
foo _ 0 = 0
foo a2 b = a3 + foo a3 (b - 1)
  where
    a3 = a3 + 1

So the problem here is that a3 = a3 + 1 is infinitely recursive - a3 can't be equal to its own value plus one. Also a2 is never used.

You said that you wanted it to refer to the value of the parameter, so now that the variables have different names we can fix this easily enough:

foo :: Int -> Int -> Int
foo _ 0 = 0
foo a2 b = a3 + foo a3 (b - 1)
  where
    a3 = a2 + 1

Note that I've left out a1 this time since it's irrelevant to the foo function. We can also get rid of the where and just inline the a2 + 1 part (and rename a2 back to a since there will no longer be multiple ones):

foo :: Int -> Int -> Int
foo _ 0 = 0
foo a b = (a + 1) + foo (a + 1) (b - 1)
Sign up to request clarification or add additional context in comments.

Comments

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.