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
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)
Related
I'm solving a practice problem in Haskell where I'm trying to count the palindrome numbers between 2 given integers. Single-digit numbers are palindromes. I've tried solving it with a helper function but I can't make it take the smaller number from the main function. Any help would be appreciated!
So far I typed this:
main :: IO()
main = do
print $ countPalindromes 5 13 == 5 -- 6 7 8 9 11
print $ countPalindromes 13 5 == 5 -- 6 7 8 9 11
rev :: Int -> Int
rev n = helper n 0
where
helper :: Int -> Int -> Int
helper 0 result = result
helper n result = helper (div n 10) (result * 10 + mod n 10)
isPalindrome :: Int -> Bool
isPalindrome x = rev x == x
countPalindromes :: Int -> Int -> Int
countPalindromes a b
| a > b = helper b a 0
| otherwise = helper a b 0
where
helper :: Int -> Int -> Int -> Int
helper a b count
| a <= b && isPalindrome (a - 1) = count + 1
| otherwise = helper (a - 1) b count
That's not your problem. The problem is that helper a b count only returns count + 1 if a is a palindrome, without ever checking if a + 1, a + 2, etc, are palindromes as well. When the first number is a palindrome, it returns 0 + 1 == 1 and done. (Your definition of helper is also counting the wrong way; it's decrementing a instead of incrementing as you need to do if you ever want a <= b to be false.)
helper needs to recurse whether or not a is a palindrome; the only difference is in the value of its third argument.
helper a b count | a > b = count -- base
| isPalindrome a = helper (a + 1) b (count + 1)
| otherwise = helper (a + 1) b count
Note that b never changes; it doesn't need to be an argument to helper. Instead, you can make a recursive call to countPalindromes to ensure a < b:
countPalindromes :: Int -> Int -> Int
countPalindromes a b
| a > b = countPalindromes b a
| otherwise = helper a 0
where
helper :: Int -> Int -> Int
helper a count
| a > b = count -- base case
| isPalindrom a = helper (a + 1) (count + 1)
| otherwise = helper (a + 1) count
Tail recursion also isn't terribly important in Haskell. You can write helper more naturally
helper a | a > b = 0
| isPalindrome a = 1 + helper (a + 1)
| otherwise = helper (a + 1)
Note, too, that the only difference between isPalindrome returning True or False is whether you add 1 or 0 to the recursive return value. You can capture that with fromEnum:
helper a | a > b = 0
| otherwise = (fromEnum (isPalindrome a)) + helper (a + 1)
As an exercise, note that you don't need explicit recursion at all. You can use filter to get the values in range that are palindromes, then simply count the number of values in the resulting list.
I think case of is quite straight forward, as i come from more imperative languages.
Nevertheless, i have encountered a Kata where one of the solutions by another user, confuses me about the use of case and Data.List (sort)
import Data.List (sort)
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c =
case sort [a,b,c] of
[min, middle, max] -> (min + middle) > max
By definition, 3 segments can make a triangle if the condition a + b > c is met for the 3 permutations of [a,b,c] so, something more straight forward (my answer) would be:
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c = a + b > c && b + c > a && a + c > b
My question is, in the case above, how is the case of testing that condition for the 3 combinations?
Imagine that a b and c are ordered from small to large, then the algorithm tests that a + b > c, which is what the first implementation checks.
If we know that a < b < c, and a + b > c holds, then we know that a + c > b holds. Indeed: a + c > a + b > c > b, hence a + c > b holds because a + b > c holds. Furthermore b + c > a + b > c > a holds, and thus b + c > a holds as well.
This thus means that checking if it holds for a known minimum, maximum and value in between, the two other equations are implied.
What the case … of does here is sorting the list [a, b, c] and unpacking the sorted list in min, middle and max, it is thus a tool that is used to assign the smallest value to min, the largest value to max and the remaining value to middle. A where … or let … in … is probably more elegant, for example:
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c = (min + middle) > max
where [min, middle, max] = sort [a, b, c]
f0 :: Int -> Int -> Int -> Int
f0 a b c = x a b - x a c - x b c
where x b a = a + b
Can someone explain me how the functions knows what to do when it gets to the...
where x b a = a + b
... statement? Does it just translate to something like this?
f0 a b c = (a + b) a b - (a + b) a c - (a + b) b c
[...] or is it just that the "x" is just another functions which takes two variables and add them [...]
Exactly. x b a = a + b is a function definition (that happens to have local scope). f0 0 0 1 = x 0 0 - x 0 1 - x 0 1. – duplode
In some other pseudo language this will look like this.
int function fo(int a, int b, int c){
int function x(int a, int b){
return a + b;
}
return x(a,b) - x(a,c) - x(b,c)
}
The way you have put it as a question,
f0 a b c = (a + b) a b - (a + b) a c - (a + b) b c
it looks like inline substitution like C macros. It is not simple code substitution. It is more like inline function. X is a function which gets called.
So I have a main function (foo) that recursively calls two other functions (step1 & step2). foo will add a1 to a2 a count amount of times and then return (a1, a2). How can I print the variables count, a1, and a2 at each step?
-- adds a1 to a2 a `count` number of times
-- returns (a1, a2) once count reaches 0
foo :: Integer -> Integer -> Integer -> (Integer, Integer)
foo count a1 a2 | count == 0 = (a1,a2)
| otherwise = foo count' a1' a2'
where (count', a1', a2') = let (count'', a1'', a2'') = step1 count a1 a2
in step2 count'' a1'' a2''
-- adds a2 to a1. How to print out count, a1 and a2' here?
step1 :: Integer -> Integer -> Integer -> (Integer, Integer, Integer)
step1 count a1 a2 = (count, a1, a2')
where
a2' = a1 + a2
-- decrements count by 1. How to print out count', a1 and a2 here? Or can I do these prints somewhere in the `foo` function?
step2 :: Integer -> Integer -> Integer -> (Integer, Integer, Integer)
step2 count a1 a2 = (count', a1, a2)
where
count' = count - 1
This is a simplified version of code from a larger code base. I am open to using a different approach. The example output that I am looking for is:
$> foo 3 4 5
3 4 5
3 4 9
2 4 9
2 4 13
1 4 13
1 4 17
0 4 17
(4, 17)
EDIT: I just realized I could probably store intermediary results in a list and then print from that list. But am I correct to think that I would have to pass the list as an argument to the functions?
You have to change foo and make it operate in the IO monad. Effectively this "tags" the function as being impure (i.e. it has side effect, such as printing on stdout) which allows it to call functions such as print. Here's an example:
foo :: Integer -> Integer -> Integer -> IO (Integer, Integer)
foo count a1 a2 = do
print (count, a1, a2)
case count of
0 -> do
print (a1,a2)
return (a1,a2)
_ -> do
let (count'', a1'', a2'') = step1 count a1 a2
(count', a1', a2') = step2 count'' a1'' a2''
foo count' a1' a2'
Note: If you want to print these values for debugging purposes, then you can use Debug.Trace as shown in chepner's answer. You should do that for debugging purposes only and for no other reason.
For debugging purposes only, you can use Debug.Trace. For example:
import Debug.Trace
-- adds a2 to a1. How to print out count, a1 and a2' here?
step1 :: Integer -> Integer -> Integer -> (Integer, Integer, Integer)
step1 count a1 a2 = traceShowID (count, a1, a2')
where
a2' = a1 + a2
-- decrements count by 1. How to print out count', a1 and a2 here? Or can I do these prints somewhere in the `foo` function?
step2 :: Integer -> Integer -> Integer -> (Integer, Integer, Integer)
step2 count a1 a2 = traceShowID (count', a1, a2)
where
count' = count - 1
traceShowID :: Show a => a -> a is basically id with the (unannounced) side effect of also printing the argument's string representation according to show.
I am new to Haskel and want to learn it. I want to print intermediate value in recursive function in haskell but i am stuck in parse error on input "=" on line b= b+50.
`main' t s a b c
| t > s = 0
| otherwise = do
print a
print b
print c
b = b + 50
c = b + 2 * a
main' (t+1) s (a+1) b c `
the C equivalent for this code is
int calculate(t,s,a,b,c)
{
printf( "%d,%d,%d",a,b,c);
if(t > s)
return 0;
else
{
b = b + 50;
c = b + 2 * a;
return calculate (t+1,s,a,b,c);
}
}
int main()
{
calculate(0,10,2,6,7);
return 0;
}`
Please help me to resolve this problem. It is not so difficult to do in C but I could not figure out how to do it in Haskel.
As PyRulez says in his comment, you need to use let syntax in do blocks. However, you are also going to run into issues because your function parameters, like all values in Haskell, are immutable. You will need to do something like:
let b' = b + 5
let c' = b' + 2 * a
If you only want to print some intermediate value, you don't need to have your function in the IO world:
you can use the Debug.Trace module:
import Debug.Trace
func :: Int -> Int -> Int -> Int -> Int
func 0 _ _ _ = 0
func t a b c = trace ("a="++(show a)++" b="++(show b)++" c="++(show c)) $ recurs
where recurs = func (t-1) (a+1) (b+50) (b+2*a)
it gives me:
> func 5 1 1 1
a=1 b=1 c=1
a=2 b=51 c=3
a=3 b=101 c=55
a=4 b=151 c=107
a=5 b=201 c=159