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.
Related
This code either returns the first factor of an Integer starting from 2 or returns nothing if it's a prime.
Example: firstFactorOf 24 returns "Just 2"
Example: firstFactorOf 11 returns "Nothing"
My question is, how would I return the value 2 rather than "Just 2" if there is a factor or return the value x if there is no factor.
firstFactorOf x
| m == Nothing = m
| otherwise = m
where m =(find p [2..x-1])
p y = mod x y == 0
//RETURNS:
ghci> firstFactorOf 24
Just 2
ghci> firstFactorOf 11
Nothing
Haskell is statically typed, meaning that you can define a function Maybe a -> a, but the question is what to do with the Nothing case.
Haskell has two functions that can be helpful here: fromMaybe and fromJust:
fromMaybe :: a -> Maybe a -> a
fromJust :: Maybe a -> a
fromJust simply assumes that you will always provide it a Just x, and return x, in the other case, it will throw an exception.
fromMaybe on the other hand expects two parameters, the first - an a is the "default case" the value that should be returned in case of Nothing. Next it is given a Maybe a and in case it is a Just x, x is returned. In the other case (Nothing) as said before the default is returned.
In your comment you say x should be returned in case no such factor exists. So I propose you define a new function:
firstFactorOfJust :: Integral a => a -> a
firstFactorOfJust x = fromMaybe x $ firstFactorOf x
So this function firstFactorOfJust calls your firstFactorOf function and if the result is Nothing, x will be returned. In the other case, the outcome of firstFactorOf will be returned (but only the Integral part, not the Just ... part).
EDIT (simplified)
Based on your own answer that had the intend to simplify things a bit, I had the idea that you can simplify it a bit more:
firstFactorOf x | Just z <- find ((0 ==) . mod x) [2..x-1] = z
| otherwise = x
and since we are all fan of optimization, you can already stop after sqrt(x) iterations (a well known optimization in prime checking):
isqrt :: Int -> Int
isqrt = floor . sqrt . fromIntegral
firstFactorOf x | Just z <- find ((0 ==) . mod x) [2..isqrt x] = z
| otherwise = x
Simplified question
For some reason there was some peculiarly complicated aspect in your question:
firstFactorOf x
| m == Nothing = m
| otherwise = m
where m =(find p [2..x-1])
p y = mod x y == 0
Why do you use guards to make a distinction between two cases that generate the exact same output? You can fold this into:
firstFactorOf x = m
where m = (find p [2..x-1])
p y = mod x y == 0
and even further:
firstFactorOf x = find p [2..x-1]
where p y = mod x y == 0
If you want it to return the first factor of x, or x, then this should work:
firstFactorOf x =
let
p y = mod x y == 0
m = (find p [2..x-1])
in
fromMaybe x m
import Data.List
import Data.Maybe
firstFactorOf x
| m == Nothing = x
| otherwise = fromJust m
where m =(find p [2..x-1])
p y = mod x y == 0
This was what I was after. Not sure why you guys made this so complicated.
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].
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)
import Data.Function (on)
import Data.List (sort)
data Monomial = Monomial
{ m_coeff :: Coefficient
, m_powers :: [(Variable, Power)]
}
deriving ()
instance Ord Monomial where
(>=) = on (>=) m_powers
instance Eq Monomial where
(==) = on (==) m_powers
That's an excerpt from my code, cut down to principal size. Let's try comparing:
*Main> (Monomial 1 [("x",2)]) > (Monomial (-1) [])
/* Computation hangs here */
*Main> (Monomial 1 [("x",2)]) < (Monomial (-1) [])
/* Computation hangs here */
On a side note, it's interesting that if I replace s/(>=)/(>)/g in instance declaration, it will not hang on the fist pair, but still will on the second:
*Main> (Monomial 1 [("x",2)]) > (Monomial (-1) [])
True
*Main> (Monomial 1 [("x",2)]) < (Monomial (-1) [])
/* Computation hangs here */
Although the standard states minimal declaration of Eq instance to be either$compare$ or $(>=)$.
What might be the problem here? (>=) on lists seems to work just fine.
Short answer:
You need to provide either (<=) or compare to have a complete definition for Ord, not (>=).
Longer explanation:
It is common for type classes in Haskell to have default implementations of some methods implemented in terms of other methods. You can then choose which ones you want to implement. For example, Eq looks like this:
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
x == y = not (x /= y)
Here, you must either implement (==) or (/=), otherwise trying to use either of them will cause an infinite loop. Which methods you need to provide is usually listed as the minimal complete definition in the documentation.
The minimal complete definition for Ord instances, as listed in the documentation, is either (<=) or compare. Since you've only provided (>=), you have not provided a complete definition, and therefore some of the methods will loop. You can fix it by e.g. changing your instance to provide compare instead.
instance Ord Monomial where
compare = compare `on` m_powers
Let's look at the default instance for Ord:
class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>), (>=) :: a -> a -> Bool
max, min :: a -> a -> a
compare x y = if x == y then EQ
-- NB: must be '<=' not '<' to validate the
-- above claim about the minimal things that
-- can be defined for an instance of Ord:
else if x <= y then LT
else GT
x < y = case compare x y of { LT -> True; _ -> False }
x <= y = case compare x y of { GT -> False; _ -> True }
x > y = case compare x y of { GT -> True; _ -> False }
x >= y = case compare x y of { LT -> False; _ -> True }
-- These two default methods use '<=' rather than 'compare'
-- because the latter is often more expensive
max x y = if x <= y then y else x
min x y = if x <= y then x else y
So, if you supply >= and == as above, only, then you are in trouble, since:
> is defined in terms of compare
But
compare is defined in terms of <=
<= is defined in terms of compare
So you have an infinite loop!
A minimum definition must defined <= or compare, not '>=`.
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