I am trying to write a simple function that takes three Int values and returns the sum of the minimum and maximum integers out of these three.
My code:
summinmax3 :: Int -> Int -> Int -> Int
summinmax3 x y z =
if (x > y && z < y)
then (x + z)
else if (y > x && z < x)
then (y + x)
else if (z > x && y < X)
then (y + z)
The code returns the error syntax error in expression (unexpected '}'), possibly due to bad layout
Any help would be appreciated
You're missing else. Every if needs both then and else, otherwise the return value wouldn't be determined, e.g. what should happen if x isn't even here?
add3IfEven x = if even x then x + 3
However, your compiler (Hugs) doesn't use your actual code, instead it transforms it into something else with curly braces:
{if … then … else … }
Since you're missing that last else, the } is unexpected. So make sure to add the correct else case. By the way, you can simply solve this exercise with maximum [x + y, x + z, y + z].
Related
I have to implement a sum function in Haskell in two ways. One function with tail recursion and the other without tail recursion.
Here is the one without tail recursion and it works perfectly
sum1 x = if x==0 then 0 else x + sum1(x-1)
Here is my attempt with tail recursion and it doesn't work:
sum2 x = help 0 y
help x y = if y==0 then x else help(x+y,y-1)
Can someone point out the mistake?
Your line:
help x y = if y==0 then x else help(x+y,y-1)
is not the correct syntax for calling a function. Because here the Haskell compiler will interpret it as:
help x y = if y==0 then x else help (x+y,y-1)
-- ^ a tuple
Instead you should write:
help x y = if y==0 then x else help (x+y) (y-1)
-- ^ two arguments
Furthermore you can also use guards, like:
helper x y | y == 0 = x
| otherwise = help (x+y) (y-1)
Finally there is also an error in the first line of sum2. It should be x instead of y:
sum2 x = help 0 x
So in full, we get:
sum2 x = help 0 x
helper s x | x == 0 = s
| otherwise = help (s+x) (x-1)
I also renamed y in the helper to x and x to s (as in sum) to make it less confusing (kudos to #Bergi for commenting on this).
Or use an eta reduction:
sum2 = help 0
Finally note that you do not need recursion for this. An implementation that would work faster is the following:
sum3 x = div (x*(x+1)) 2
Since:
n
---
\ (n+1) n
/ i = -------
--- 2
i=1
I'm currently working through The Craft of Functional Programming 2nd Edition and I have been presented with a task to write a between function which has stumped me.
The function takes three numbers as arguments and returns a boolean result i.e.
between :: Int -> Int -> Int -> Bool
It is defined so that between m n p is true if n is between n and p. For the sake of simplicity given between 2 2 2, the function would return true, also between 3 3 5 would return true.
Mathematically, x<=y and y<=z
The question also recommended that I could write a weakAscendingOrder function which checks that the number sequence doesn't go down at any point. I have written this function and my code is shown below:
weakAscendingOrder :: Int -> Int -> Int -> Bool
weakAscendingOrder x y z = (x <= y) && (y <= z)
How can I write a between function, either with or without using weakAscendingOrder, while preserving the function signatures since they have been provided by the book?
Comment two is exactly right. The weakAscendingOrder function behaves exactly like you want between to behave. Here are some additional flavors of implementation:
between x y z --using guards
|x <= y = y <= z
|otherwise = False
between x y z = if (x <= y) then (y <= z) else False --using if
between x y z = case (x <= y) of True -> (y <= z) --using case syntax
False -> False
however the (x<=y)&&(y<=z) is in my opinion very readable and does the job nicely.
I want to write a Haskell program that calculates the sum of numbers between 2 given numbers.
I have the following code:
sumInt :: Int -> Int -> Int
sumInt x y
| x > y = 0
| otherwise = x + sumInt x+1 y
But when I compile it I get the following error:
SumInt is applied to too few arguments.
I don't understand what I'm doing wrong. Any ideas?
You need parentheses around x+1:
| otherwise = x + sumInt (x + 1) y
The reason is that function application binds more tightly than operators, so whenever you see
f x <> y
This is always parsed as
(f x) <> y
and never as
f (x <> y)
I have a function that returns Floats (or some other type). I am using my program as a module in ghci. How would I print out info at certain points in the program? For example, if I detect bad input to a function, how do I print out an error message?
There are a few cases here, depending on what you want to do.
The straight forward sprinkling of printfs as a method of debugging is not going to work very well in Haskell.
If you have a partial function, I would suggest using Either or Maybe as a solution.
For example:
lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
lookup x [] = Nothing
lookup x ((k,v):ys) | x == k = Just v
| otherwise = lookup x ys
lookup takes a key, and a list of key-value pairs and return Just the value associated with that key, or Nothing if the key is not in the list.
doMath :: Char -> Int -> Int -> Either String Int
doMath '+' x y = Right (x + y)
doMath '*' x y = Right (x * y)
doMath '/' x 0 = Left "Division by zero"
doMath '/' x y = Right (x / y)
doMath '-' x y = Right (x - y)
doMath c x y = Left ("Bad operator: " ++ show c)
Either is like maybe, in that if you can, you will return the right result. Otherwise you take what's left.
If your function really has an impossible case, then you can use the function error, which throws a pretty much uncatchable error with a string. It's not pretty, but it will help point you in the right direction when doing a post-mortem after the impossible does happen.
Because there are no side effects in pure code, you basically have three options:
You can print an error message and throw an exception, which usually terminates the program unless you catch it:
myDiv x 0 = error "Division by zero"
myDiv x y = x / y
You can print an error message and return some value:
import Debug.Trace
myDiv x y = trace ("Trying to divide " ++ show x ++ " by " ++ show y) (x / y)
You can return a value which describes the error in some way, e.g. Maybe or Either String:
myDivMaybe x 0 = Nothing
myDivMaybe x y = Just (x / y)
myDivEither x 0 = Left "Won't divide by zero"
myDivEither x y = Right (x / y)
You usually use error when the input is really invalid and you don't mind a runtime error in that case. trace is usually used for debugging purposes. If you want to avoid runtime errors on invalid input, you can use Maybe or Either.
I am doing problem 112 on Project Euler and came up with the following to test the example case (I'll change the number in answer to 0.99 to get the real answer):
isIncre x | x == 99 = False
| otherwise = isIncre' x
where
isIncre' x = ???
isDecre x = isIncre (read $ reverse $ show x :: Int)
isBouncy x = (isIncre x == False) && (isDecre x == False)
bouncers x = length [n|n<-[1..x],isBouncy n]
nonBouncers x = length [n|n<-[1..x],(isBouncy n) == False]
answer = head [x|x<-[1..],((bouncers x) / (nonBouncers x)) == 0.5]
But what I don't know how to do is define a function isIncre' which tests to see if the digits in a number are greater than or equal to the one on their left. I know it needs to be done recursively but how?
On a side note, I know I can only use / on two floating point numbers but how can I make the output of bouncers to be floating point number instead of an integer?
Edit:
Thanks for the help, but it didn't like the = when I changed isIncre to:
isIncre x | x <= 99 = False
| otherwise = isIncre' (mshow x)
where
isIncre' (x:y:xs) = (x <= y) && (isIncre' (y:xs))
isIncre' _ = True
The number 0.99 cannot be represented exactly in base 2. Hence you may want to avoid the use of floating point numbers for this assignment. Instead, to see whether exactly 99% of the numbers <= x are bouncers, test whether
100 * (x - bouncers x) == x
This works because it is (mathematically) the same as (x - bouncers x) == x / 100, which is true if (x - bouncers x) (the number of non-bouncy numbers) is 1% of x. Observe that there is thus no need to define nonBouncers.
Also, another way to define bouncers is
bouncers x = length $ filter isBouncy [1..x]
However, you should reconsider your design. Currently you are recalculating the number of bouncy numbers up to x, for every x that you try. So a lot of work is being done over and over. What you may instead want to do, is generate a sequence of tuples (x, n), where n is the number of bouncy numbers <= x. Observe that if there are n bouncy numbers <= x, then there are either n or n + 1 bouncy number <= x + 1.
More specifically, to calculate (x + 1, n'), all you need is (x, n) and the output of isbouncy (x + 1).
If you have a string representation of an integer number, you could write the isIncre function like this (ord converts a character to an integer and string is just a list of chars):
isIncre (x:y:xs) = ord x <= ord y && isIncre (y:xs)
isIncre _ = True
It could be even nicer to write the isIncre function without ord, working on any ordered type, then combine it with "map ord" when you call it instead. The implementation would then be just:
isIncre (x:y:xs) = x <= y && isIncre (y:xs)
isIncre _ = True
That could be called like this, if x is an integer number
isIncre (map ord (show x))
I would use really nice functional version of isIncre if you have string representation of intetger.
isIncre :: (Ord a) => [a] -> Bool
isIncre list = and $ zipWith (<=) list (tail list)
If not, just compose it with show.
isIncreNum :: Integer -> Bool
isIncreNum = isIncre . show