I can count number of positive occurrence with this:
count :: [Int] -> Int
count xs = length [ x | x <- xs, x > 0]
However, I can't make it work to count both positive and negative numbers.
For the input [1,2,3, -1,-2] I want (3,2) as an output. How can I achieve this?
You can work with a "fold". Here you pass a 2-tuple as "accumulator" and you increment one of the two, depending on whether the item is positive or negative.
This thus looks like:
import Data.Foldable(foldl')
count_pn :: (Num a, Ord a) => [a] -> (Int, Int)
count_pn = foldl' f (0, 0)
where f (np, nn) x
| … = …
| otherwise = …
Here you need to still implement the f function. Here (np, nn) is the 2-tuple with the amount of positive and negative items counted so far, and x the element we want to count next.
Related
Implement the populationBelow :: Int -> [(String, Int)] -> [String] function, that returns the names of the countries from the given table whose population (million people) is less than the number given in the parameter.
For example:
populationBelow 10 [ ("Hungary", 9.773),
("Japan", 126.8),
("Iceland", 0.3604),
("United States", 327.2),
("Mongolia", 3.076)
] == ["Hungary", "Iceland", "Mongolia"]
populationBelow 0 [ ("Hungary", 9.773),
("Japan", 126.8),
("Iceland", 0.3604),
("United States", 327.2),
("Mongolia", 3.076)] == []
So far, I've tried:
populationBelow x ((y, z):ys) | z < x = [y] ++ populationBelow x (ys)
| otherwise = (y) : populationBelow x (ys)
Which doesn't work for fractional numbers and if the table contains more than one element that meets the criteria, I get a Non-exhaustive patterns error.
populationBelow :: RealFrac a => a -> [(String, a)] -> [String]
populationBelow _ [] = []
populationBelow x ((y, z):ys)
| z < x = y : populationBelow x ys
| otherwise = populationBelow x ys
There are a few problems with the current code:
The base case for the empty list (hence the non-exhaustive pattern error), whether it has been exhausted because of recursion or it was empty in the first place is missing.
you are adding y to the result regardless of the result of the condition. In the first case by concatenating and the second by adding it to the head of the result of the recursive call. y should only be added if its population is below the given threshold.
The signature provided by your function suggests it only uses integers but the input example have decimal numbers. I have changed the signature to accept decimal numbers.
You're definitely on the right track. To be able to deal with fractional numbers, you should make your type signature a bit more general. Also, rather straightforward filtering tasks are arguably most elegantly expressed as list comprehensions:
populationBelow :: Ord b => b -> [(a, b)] -> [a]
populationBelow k xs = [x | (x, n) <- xs, n < k]
Indeed:
> populationBelow 10 [("Hungary", 9.773), ("Japan", 126.8), ("Iceland", 0.3604), ("United States", 327.2), ("Mongolia", 3.076)]
["Hungary","Iceland","Mongolia"]
I wrote a solution for a very simple practice problem:
Calculate the number of grains of wheat on a chessboard given that the number on each square doubles. Write code that shows how many grains are on a given square, and the total number of grains on the chessboard.
The function must return a Maybe Integer and return Nothing if the input is less than 1 or greater than 64.
square :: Integer -> Maybe Integer
square n = if (n < 1 || n > 64) then Nothing else Just (2^(pred n))
total :: Integer
total = sum (fmap sum (map square [1..64]))
I tried to apply fmap sum to some test output of map square (list of Maybe Integer) in GHCI and was surprised to discover it returns the list of integers (sans Just) rather than their sum. So in the solution above I apply sum a second time to actually get the sum.
I would like to understand conceptually why this is the case: in other words why is sum behaving like a converter for Maybe Ints to Ints in this context instead of adding things?
I've solved some similar exercises relying on helper functions to avoid complications of doing computation on Maybe values, and perhaps in this case I should just calculate the value of total without utilizing square, i.e.:
total = sum [2^n | n <- [0..63]]
However since I'd already written a useful function my first instinct was to reuse it, which led to some unforeseen behavior.
Let's look at the type of sum:
sum :: (Foldable t, Num a) => t a -> a
Often, for a beginner, this is simplified by assuming that t ~ [], so that we instead use sum as
sum :: Num a => [a] -> a
If we try to use sum at this type in your example, we will get a type error, because you have a list of Maybe numbers, not a list of numbers. Instead you write fmap sum [Just 1], specializing sum and fmap to:
sum :: Maybe Integer -> Integer
fmap :: (Maybe Integer -> Integer) -> [Maybe Integer] -> [Integer]
So the question isn't really "why isn't sum adding things", so much as "how can sum have a meaningful definition when given a single Maybe Integer?"
One way to answer that question, if you're not familiar with how to interpret sum as working on Foldable or how Maybe is foldable, is to just try implementing it yourself. There's really only one reasonable implementation:
sum :: Maybe Integer -> Integer
sum Nothing = 0
sum (Just x) = x
Right? Someone asked you "what's the total of the numbers in here", and then gave you either zero or one number. Pretty easy to add up. That's exactly how sum works for Maybe, except that it goes through Foldable instead of being specialized to Maybe.
After this, of course it's easy: you've turned your [Maybe Integer] into an [Integer], and of course summing that gets you the sum of the non-Nothing entries.
Let's look at an example.
map square [0..2] = [Nothing, Just 1, Just 2]
fmap sum (map square [0..2]) = [sum Nothing, sum (Just 1), sum (Just 2)]
Since Maybe is a Foldable container, it makes sense to calculate the sum of its elements:
sum Nothing = 0
sum (Just a) = a
So
fmap sum (map square [0..2]) = [0, 1, 2]
Now I don't know what you were actually hoping to do with the Maybes, but this is why you got what you got.
One thing worth internalising; when you map a function over a list1, the result is always going to be a list with the same number of elements. The function will be applied to each element of the list individually; it cannot combine them into a single summary value. That's just not what fmap does.
So with that principle in mind, we know that fmap sum squares (where squares = map square [1..64]) cannot possibly result in the sum of squares. It's going to be [ sum (square 1), sum (square 2), ... , sum (square 64) ]. We will then need to apply sum again to that whole list, if we want to actually add them up.
That just leaves an explanation for what sum (square 1) etc is actually doing (i.e. what sum does when applied to Maybe values). The proper type for sum is sum :: (Foldable t, Num a) => t a -> a. Foldable is basically the type-class of structures that you can scan for 0 or more elements in order (essentially: those you can convert to a list). All sum does is add up the elements that are there, however many there are (and use 0 as a "starting value" in case there are no elements). Maybe has a Foldable instance; it always has 0 or 1 elements, and sum can add those up just as well as it can add up lists that happen to have only 0 or 1 elements.
Of course the effect of summing zero-or-one numbers is just that the result is 0 if there were zero inputs and equal the input number if there was one. + never actually gets called for this "sum", which makes it feel a little pointless. But sum didn't know that; it works for any Foldable, regardless of how many elements they contain. And Maybe didn't know that it would end up being used to "sum without actually adding"; it just implemented Foldable so that any other function that wants to scan a variable number of elements out of a structure can scan Maybes.
If you think it's silly, just don't use sum for that job; use fromMaybe 0 instead.
1 You can generalise this to other functors beyond lists; when you fmap a function over a data structure, the result will have exactly the same structure as the input. Only the "leaf nodes" will be different.
First of all, the fmap in
total = sum (fmap sum (map square [1..64]))
is just map:
total = sum ( map sum (map square [1..64]))
and the maps compose by composing their mapping functions,
total = sum ( map (sum . square) [1..64] )
and a map applies its function to each element of the list,
total = sum [sum (square x) | x <- [1..64] ]
while a composed function finds its result in steps,
total = sum [sum y | x <- [1..64], y <- [square x] ]
whereas the inner sum is working with the result of square, namely, a Maybe number,
total = sum [ n | x <- [1..64], Just n <- [square x] ]
= sum [ n | x <- [1..64], Just n <- list (square x) ]
where list y = [y]
and turning sum y into just n works because sum finds a sum and 0 is its identity, so adding a 0 is the same as not adding anything at all. Meaning, the Just n pattern match fails when square produces a Nothing (which in our case is never, but never mind that) so that x which causes it is skipped over.
total = sum [ n | x <- [1..64], n <- maybeToList (square x) ]
= sum [ n | x <- [1..64], n <- case (square x) of
Just n -> [n]
Nothing -> [] ]
But again, we know that this never happens, and all this repackaging of the same number is all for naught, so in the end your code is equivalent to
total = sum [ n | x <- [1..64], Just n <- [Just (2^(x-1))] ]
= sum [ n | x <- [1..64], n <- [ 2^(x-1) ] ]
= sum [ 2^(x-1) | x <- [1..64] ]
just as you intended.
Seeing is better than believing (well, remembering / imagining, which is needed when using higher order functions ... unless of course one has an eidetic memory so for them believing is seeing). It might even give us new ideas for further code simplification, some transformations, and, eventually, maybe even some computational optimizations:
total = sum [ 2^x | x <- [0..63] ]
= sum [ product (replicate x 2) | x <- [0..63] ]
= sum $ [ product (replicate 0 2) ]
++ [ product (replicate x 2) | x <- [1..63] ]
= sum $ [ product [] ]
++ [ 2 * product (replicate (x-1) 2) | x <- [1..63] ]
= sum $ [ 1 ]
++ [ 2 * product (replicate x 2) | x <- [0..62] ]
= sum [1] + sum ( [2*n0] ++
[ 2 * product (replicate x 2) | x <- [1..62] ] )
where { n0=1 }
= n0 + sum [n1] + sum( [2*n1] ++
[ 2 * product (replicate x 2) | x <- [2..62] ] )
where { n0=1 ; n1=2*n0 }
= n0 + n1 + n2 + sum( [2*n2] ++
[ 2 * product (replicate x 2) | x <- [3..62] ] )
where { n0=1 ; n1=2*n0 ; n2=2*n1 }
= ....
= sum . take 64 $ iterate (2*) 1
And there they are again, the 64 squares of the chess board, and the first single grain of rice, which is doubled, and doubled again, as we ago along the squares.
I want to make a function in haskell that given a list of single digits, i make the full number. I was thinking in using intensive lists and patrons, as the code it follows:
funcion5 (x:xs) = [y*(10^w) | y <- (x:xs) w]
The idea is, to go over the list and multiplie each digit to 10 pow to the position of the number. Finally i only have to sum all digits and I have the number as this:
sum (funcion5 (x:xs))
Can anyone help me, please? Thanks
This may simply be done by folding with foldl1 :: Foldable t => (a -> a -> a) -> t a -> a as follows;
Prelude> foldl1 (\x y -> 10*x+y) [1,2,3]
123
You can use a "fold" pattern for this. We thus write this in terms of foldl :: (a -> b -> a) -> a -> [b] -> a:
function5 :: Num n => [n] -> n
function5 = foldl f 0
where f a x = ...
So here f takes two parameters a (the thus far generated number), and x the next digit.
In a positional notation system, one can obtain the value by "scanning" left-to-right and each time multiplying the thus far obtained value with the radix, and adding the next digit. So this is the logic you need to "encode" in f: taking the thus far obtained value, and the next digit, and producing the next value.
multiplos_10 = [10^x | x <- [0..]]
aux (x:xs) = sum ([a*b | (a,b) <- zip (x:xs) multiplos_10])
a_numero (x:xs) = aux (reverse(x:xs))
I am new to Haskell and I am trying some stuff out. I am having some trouble comparing tuples elements.
Let's say I have a tuple [(1,3),(2,1),(4,4)].
I want to compare each pair index with each other and save some data into a counter value and return that value.
For example what I want is this:
Tuple: [(a,b),(c,d),(e,f)]
When a>b I want to add 3 to the counter.
When a==b I want to add 1 to the counter.
Otherwise add 0 to the counter. Same for (c,d) and (e,f).
After iterating through my tuples I want to return the counter.
So in my example I have tuple [(1,3),(2,1),(4,4)].
The function should do
Since 1<3 add 0 to counter.
Since 2>1 add 3 to counter.
Since 4=4 add 1 to counter.
And after all return 0+3+1 = 4.
Any ideas? Thank you in advance!
(Edit)
calculateWins :: [(Int,Int)]->Int
calculateWins d ((a,b) :xs) = x
where x
|a>b = 3
|a==b = 1
|otherwise = 0
This looks like the point system of a soccer cup (and some other sports). Instead of implementing a function that calculates the sum, we better first aim to calculate something that calculates the score for one such tuple, so something like:
score :: Ord a => (a, a) -> Int
By using a as type, we can use any type of values, as long as we can compare them (the Ord type constraint). So we can write something like:
score (x, y) = -- ...
now in case x > y, then the score is 3 points, in case x == y, then the score is 1 point, and finally in case x < y (otherwise), then the score is 0 points, so we can write it as:
score :: Ord a => (a, a) -> Int
score (x, y) | x > y = 3
| x == y = 1
| otherwise = 0
So now we can perform a map score to calcuate a list of scores, and by using sum, we can calculate the sum of those points, like:
calculateWins :: Ord a => [(a, a)] -> Int
calculateWins = sum . map score
Hint: use a function of type (a -> b) -> [a] -> [b] to transform the list of tuple into a list of your summands (3 or 1 or 0), and use another function of type [a] -> a to get the sum.
The Hoogle is a very nice site for looking up Haskell functions, both by name and by signature.
Please do try these things out before simply asking for the complete code; that helps neither of us.
I am trying to create a function that receives a range of doubles (Double, Double) and an n (Int), where I divide this interval into n equal parts. I know that if it was a list, I did a Split in the list, but being in tuples and getting Doubles, I'm not sure what to do.
Thank you for any help
This is similar to #mschmidt's answer, but I think a list comprehension is probably clearest:
intervals :: Int -> (Double,Double) -> [(Double,Double)]
intervals n (a,b) =
let n' = fromIntegral n
d = (b - a) / n'
in [(a + i*d, a + (i+1)*d) | i <- [0..n'-1]]
giving:
> intervals 4 (1,10)
[(1.0,3.25),(3.25,5.5),(5.5,7.75),(7.75,10.0)]
>
If the duplicate calculation of the endpoint offends you, you could write:
intervals' :: Int -> (Double,Double) -> [(Double,Double)]
intervals' n (a,b) =
let n' = fromIntegral n
d = (b - a) / n'
x = [a + i*d | i <- [0..n']]
in zip x (tail x)
Note that zip x (tail x) is a pretty standard way to get tuples of consecutive pairs of a list:
> let x = [1,2,3,4] in zip x (tail x)
[(1,2),(2,3),(3,4)]
>
A rough sketch, probably not the most elegant solution:
Take the two input doubles (I call them l and u) and compute the width of the input range/interval.
You want to compute n output ranges of equal width w. Compute this w by dividing the input width by n.
Build a list of length n containing the values l+0*w, l+1*w, l+2*w, ...
Build the list of output tuples by combining the first two items in the list into a tuple. Drop one element of the list. Continue until only one element remains.
Try to catch all possible errors