Haskell, Local definition and variables, confused :/ - haskell

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.

Related

about the use of "case of" in Haskell

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]

Haskell code using a pre definite variable

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)

Assigning special cases when certain variables have certain values?

for my functional programming homework I am instructed to write a function that gives back the real solutions of a quadratic equation in a list, I used the discriminant to find them out.
So, my code looks something like this:
quadSols::Double->Double->Double->[Double]
quadSols a b c = [x1,x2]
where
x1 = (-b - sqrt d) / (2 * a)
x2 = (-b + sqrt d) / (2 * a)
d = (b * b) - 4 * a * c
Now, the problem is in the case a = 0, for which the solution would be simply x = -c / b.
I tried something like this, it sounds completely wrong but I don't really know what to do.
if a == 0 then quadSols a b c = [x]
and then added to the "where" part:
x = -c / b
when trying to load it with ghci I get:
parse error on input ‘=’
Failed, modules loaded: none.
Can anyone provide me with some guidance?
You can simply pattern match for the case where a == 0:
quadSols :: Double -> Double-> Double-> [Double]
quadSols 0 b c = [x]
where x = -c / b
quadSols a b c = [x1,x2]
where
x1 = (-b - sqrt d) / (2 * a)
x2 = (-b + sqrt d) / (2 * a)
d = (b * b) - 4 * a * c
Note that you must include the first case before the second, since cases are matched in the order they are declared.
You can add another equation to quadSols:
quadSols 0 b c = [x]
where
x = (-c) / b
quadSols a b c = [x1,x2]
where
…
Or use a guard:
quadSols a b c
| a == 0 = [x]
| otherwise = [x1,x2]
where
x = (-c) / b
…
Due to laziness, the definitions in the where clause won’t be evaluated unless necessary to produce a result.

Printing intermediate value in recursive function in Haskell

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

How do I return the middle number in Haskell

I have the following beginning of a function, and am unsure as to how I should return Middle Number (i.e. the number that is neither the largest nor smallest):
middleNumber :: Int -> Int -> Int -> Int
middleNumber a b c
| ...
I would recommend you break the function into two steps: First, sort the three numbers. Then, take the middle element. For the first step, also consider if you can take it one step at a time; each step bringing it a bit closer to being fully sorted, then tail-recursing back to bring it even closer.
The "middle number" is larger than one of the numbers, but smaller than the other number. And there is only one middle number. The most mechanical way to solve this would be to start off
middleNumber a b c
| a < b && a > c = a
Check if a is the middle number by being less than b but greater than c.
Now what if a is the middle number, but it's actually greater than b and less than c? There's another guard. What if b is the middle number? There's another 2 guards. What if c is the middle number? There's 2 more guards, for a total of 6 different cases.
(btw, the expression | a < b && a > c = a is referred to as a guard. If you don't have a firm grasp yet of what guards are, then I recommend LYAH # Guards)
Of course there are better ways to write the function, but for understanding purposes it's good to be able to manually and systematically break down all of the possible situations, and determine what to do in each situation. How To Design Programs is a great book for learning how to be systematic in this way.
The obligatory Rube-Goldberg-answer:
import Control.Applicative
middleNumber a b c = sum $ [sum, negate.minimum, negate.maximum] <*> [[a,b,c]]
[Edit]
Here is another version:
middleNumber a b c = fst $ maximumBy (compare `on` abs.snd) [(a,b-c),(b,c-a),(c,a-b)]
I'm sure we could translate this to arrow syntax for further obfuscation, but I leave that task to the interested reader.
Expanding on Dan Burton's answer with guards, I evaluate a, b, c cases each in its own guard. However, what happens when 2 of the numbers are equal? Then the middle number should be one of the duplicated ones.
middleNumber :: Int -> Int -> Int -> Int
middleNumber a b c
| (a > b && a < c) || (a > c && a < b) = a
| (b > a && b < c) || (b > c && b < a) = b
| (c > a && c < b) || (c > b && c < a) = c
| otherwise = if a == b then a else c
I did a quick brute force method but this is most certainly not the best solution
import Data.List
middleNum :: Int -> Int -> Int -> Int
middleNum a b c = (\[_,m,_] -> m) $ sort $ a:b:c:[]
Obviously this is an awful idea as it explicitly relies on there being 3 items in the list, but it does the job
You can leverage guards and where to obtain the same result in simple way:
middleNumber :: Int -> Int -> Int -> Int
middleNumber x y z
| a == x = max y z
| a == y = max x z
| a == z = max x y
where
a = max x $ max y z
If you don't have access to the built-in max. you can easily write your own.
max' :: Int -> Int -> Int
max' x y
| x > y = x
| otherwise = y

Resources