I'm trying to write a program in Haskell
that gets a list (of integer) and prints out the number of elements that are bigger than the list's average
So far I tried
getAVG::[Integer]->Double
getAVG x = (fromIntegral (sum x)) / (fromIntegral (length x))
smallerThanAVG:: [Integer]->Integer
smallerThanAVG x = (map (\y -> (if (getAVG x > y) then 1 else 0)) x)
For some reason I'm getting this error
Couldn't match expected type `Double'
against inferred type `Integer'
Expected type: [Double]
Inferred type: [Integer]
In the second argument of `map', namely `x'
It could be that I haven't written the logic correctly, although I think I did..
Ideas?
These errors are the best kind, because they pinpoint where you have made a type error.
So let's do some manual type inference. Let's consider the expression:
map (\y -> (if (getAvg x > y) then 1 else 0)) x
There are a few constraints we know off the bat:
map :: (a -> b) -> [a] -> [b] -- from definition
(>) :: Num a => a -> a -> Bool -- from definition
getAvg :: [Integer] -> Double -- from type declaration
1, 0 :: Num a => a -- that's how Haskell works
x :: [Integer] -- from type declaration of smallerThanAVG
Now let's look at the larger expressions.
expr1 = getAvg x
expr2 = (expr1 > y)
expr3 = (if expr2 then 1 else 0)
expr4 = (\y -> expr3)
expr5 = map expr4 x
Now let's work backwards. expr5 is the same as the RHS of smallerThanAVG, so that means it has the same result type as what you've declared.
expr5 :: Integer -- wrong
However, this doesn't match our other constraint: the result of map must be [b] for some b. Integer is definitely not a list (although if you get facetious, it could be coerced into a list of bits). You probably meant to sum that list up.
expr6 = sum expr5
sum :: Num a => [a] -> a
Now let's work forwards.
expr1 :: Double -- result type of getAvg
y :: Double -- (>) in expr2 requires both inputs to have the same type
expr4 :: (Integer -> [a]) -- because for `map foo xs` (expr5)
-- where xs :: [a], foo must accept input a
y :: Integer -- y must have the input type of expr4
Herein lies the conflict: y cannot be both a Double and an Integer. I could equivalently restate this as: x cannot be both a [Double] and [Integer], which is what the compiler is saying. So tl;dr, the kicker is that (>) doesn't compare different types of Nums. The meme for this sort of problem is: "needs more fromIntegral".
(getAvg x > fromIntegral y)
Your code has two errors.
Although the type signature in the code declares that smallerThanAVG x evaluates to an Integer, its code is map ... x, which clearly evaluates to a list instead of a single Integer.
In the code getAVG x > y, you are comparing a Double to an Integer. In Haskell, you can only compare two values of the same type. Therefore, you have to use fromIntegral (or fromInteger) to convert an Integer to a Double. (This is essentially what caused the error message in the question, but you have to get used to it to figure it out.)
There are several ways to fix item 1 above, and I will not write them (because doing so would take away all the fun). However, if I am not mistaken, the code you are aiming at seems like counting the number of elements that are smaller than the average, in spite of what you write before the code.
Styling tips:
You have many superfluous parentheses in your code. For example, you do not have to parenthesize the condition in an if expression in Haskell (unlike if statement in C or Java). If you want to enjoy Haskell, you should learn Haskell in a good style instead of the Haskell which just works.
You call the variable which represents a list “x” in your code. It is conventional to use a variable name such as xs to represent a list.
Others have explained the errors beautifully.
I'm still learning Haskell but I'd like to provide an alternative version of this function:
greaterThanAvg :: [Int] -> [Int]
greaterThanAvg xs = filter (>avg) xs
where avg = sum xs `div` length xs
cnt = length $ greaterThanAvg [1,2,3,4,5]
Related
I'm trying to learn Haskell and the small bit of sample code I tried to understand is compiling, but while applying the code I was running into a "Couldn't match expected type" error.
Can anyone give me some guidance as to what I'm doing wrong/how I should go about this?
This code was given in a lecture:
> mult :: Integer -> (Integer, Integer-> Integer )
> mult x = (x,(*x))
Executing snd (mult 3) 5 as I was told in the lecture I get
15
However when executing (mult 3) 5 I get the following error
<interactive>:133:1: error:
• Couldn't match expected type ‘Integer -> t’
with actual type ‘(Integer, Integer -> Integer)’
• The function ‘mult’ is applied to two arguments,
but its type ‘Integer -> (Integer, Integer -> Integer)’
has only one
In the expression: (mult 3) 5
In an equation for ‘it’: it = (mult 3) 5
• Relevant bindings include it :: t (bound at <interactive>:133:1)
Seeing the error I have tried to apply mult with one argument mult 3 which resulted in the following error
<interactive>:135:1: error:
• No instance for (Show (Integer -> Integer))
arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of an interactive GHCi command: print it
Why can't I use mult without the snd function?
(Integer, Integer -> Integer)
This is not a function. It might look kind of like a function of two arguments, but it's actually parenthesized as (Integer, (Integer -> Integer))
so it's a tuple, where the first thing is just an ordinary number and the second is a function.
mult :: Integer -> (Integer, Integer -> Integer)
mult x = (x, (*x))
Here, we take a number x and return a 2-tuple. The first element of this tuple is just the number x, nothing more and nothing less. The second element is a function which multiplies by x. These are two distinct values, not tied together in any way.
fst (mult 3)
This is the first element of the tuple, which is just a number. In this case, we'll get 3.
snd (mult 3)
This is the second element of the tuple, a function from Integer to Integer. We can't print out functions in Haskell (since they don't implement Show), so we have to apply it to an argument in order to get a result.
snd (mult 3) 5 -- Or, equivalently, (snd (mult 3)) 5
This applies the function "multiply by 3" to the number 5, so we get 5 times 3, or 15.
(mult 3) 5
This takes a tuple mult 3 (whose value is (x, (* x))), and attempts to apply it to a number. In Haskell, only functions can be given arguments, and a tuple is not a function, so you get an error that basically says "I expected a function here, but I got a tuple".
Why can't I use mult without the snd function?
Because mult 5 returns a 2-tuple, it returns (5, (* 5)), so the first item is an Integer whereas the second is a function with type Integer -> Integer.
You cannot use this 2-tuple as a function when you apply 3 to it. What would the result of (5, (* 5)) 3 be? By using snd (5, (* 5)) it returns (* 5), and then you can use that for (* 5) 3, which is 15.
Furthermore you cannot use show f with f a function, since for a generic function, that cannot produce output. Using printing the result of mult 3 is thus not possible, you can print fst (mult 3) for example, which is 3.
I want to add two positive numbers together without the use of any basic operators like + for addition. I've already worked my way around that (in the add''' function) (i think) may not be efficient but thats not the point right now. I am getting lots of type errors however which i have no idea how to handle, and is very confusing for me as it works on paper and i've come from python.
add 1245 7489
--add :: Int -> Int -> Int
add x y = add'' (zip (add' x) (add' y))
where
add' :: Int -> [Int]
add' 0 = []
add' x = add' (x `div` 10) ++ [x `mod` 10]
conversion [1,2,4,5] [7,4,8,9] then zipping them together [(1,7),(2,4)....]
add'' :: [(Int,Int)] -> [Int]
add'' (x:xs) = [(add''' (head x) (last x))] ++ add'' xs
summary [8,6,...] what happens when the sum reaches 10 is not implemented yet.
where
--add''' :: (Int,Int) -> Int
add''' x y = last (take (succ y) $ iterate succ x)
adding two numbers together
You can't use head and last on tuples. ...Frankly, you should never use these functions at all because they're unsafe (partial), but they can be used on lists. In Haskell, lists are something completely different from tuples.To get at the elements of a tuple, use pattern matching.
add'' ((x,y):xs) = [add''' x y] ++ add'' xs
(To get at the elements of a list, pattern matching is very often the best too.) Alternatively, you can use fst and snd, these do on 2-tuples what you apparently thought head and last would.
Be clear which functions are curried and which aren't. The way you write add''', its type signature is actually Int -> Int -> Int. That is equivalent to (Int, Int) -> Int, but it's still not the same to the type checker.
The result of add'' is [Int], but you're trying to use this as Int in the result of add. That can't work, you need to translate from digits to numbers again.
add'' doesn't handle the empty case. That's fixed easily enough, but better than doing this recursion at all is using standard combinators. In your case, this is only supposed to work element-wise anyway, so you can simply use map – or do that right in the zipping, with zipWith. Then you also don't need to unwrap any tuples at all, because it works with a curried function.
A clean version of your attempt:
add :: Int -> Int -> Int
add x y = fromDigits 0 $ zipWith addDigits (toDigits x []) (toDigits y [])
where
fromDigits :: Int -> [Int] -> Int
fromDigits acc [] = acc
fromDigits acc (d:ds)
= acc `seq` -- strict accumulator, to avoid thunking.
fromDigits (acc*10 + d) ds
toDigits :: Int -> [Int] -> [Int] -- yield difference-list,
toDigits 0 = id -- because we're consing
toDigits x = toDigits (x`div`10) . ((x`mod`10):) -- left-associatively.
addDigits :: Int -> Int -> Int
addDigits x y = last $ take (succ x) $ iterate succ y
Note that zipWith requires both numbers to have the same number of digits (as does zip).
Also, yes, I'm using + in fromDigits, making this whole thing pretty futile. In practice you would of course use binary, then it's just a bitwise-or and the multiplication is a left shift. What you actually don't need to do here is take special care with 10-overflow, but that's just because of the cheat of using + in fromDigits.
By head and last you meant fst and snd, but you don't need them at all, the components are right there:
add'' :: [(Int, Int)] -> [Int]
add'' (pair : pairs) = [(add''' pair)] ++ add'' pairs
where
add''' :: (Int, Int) -> Int
add''' (x, y) = last (take (succ y) $ iterate succ x)
= iterate succ x !! y
= [x ..] !! y -- nice idea for an exercise!
Now the big question that remains is what to do with those big scary 10-and-over numbers. Here's a thought: produce a digit and a carry with
= ([(d, 0) | d <- [x .. 9]] ++ [(d, 1) | d <- [0 ..]]) !! y
Can you take it from here? Hint: reverse order of digits is your friend!
the official answer my professor gave
works on positive and negative numbers too, but still requires the two numbers to be the same length
add 0 y = y
add x y
| x>0 = add (pred x) (succ y)
| otherwise = add (succ x) (pred y)
The other answers cover what's gone wrong in your approach. From a theoretical perspective, though, they each have some drawbacks: they either land you at [Int] and not Int, or they use (+) in the conversion back from [Int] to Int. What's more, they use mod and div as subroutines in defining addition -- which would be okay, but then to be theoretically sound you would want to make sure that you could define mod and div themselves without using addition as a subroutine!
Since you say efficiency is no concern, I propose using the usual definition of addition that mathematicians give, namely: 0 + y = y, and (x+1) + y = (x + y)+1. Here you should read +1 as a separate operation than addition, a more primitive one: the one that just increments a number. We spell it succ in Haskell (and its "inverse" is pred). With this theoretical definition in mind, the Haskell almost writes itself:
add :: Int -> Int -> Int
add 0 y = y
add x y = succ (add (pred x) y)
So: compared to other answers, we can take an Int and return an Int, and the only subroutines we use are ones that "feel" more primitive: succ, pred, and checking whether a number is zero or nonzero. (And we land at only three short lines of code... about a third as long as the shortest proposed alternative.) Of course the price we pay is very bad performance... try add (2^32) 0!
Like the other answers, this only works for positive numbers. When you are ready for handling negative numbers, we should chat again -- there's some fascinating mathematical tricks to pull.
nFibbo :: [x] -> [x]
nFibbo x = x ++ sum x
I'm trying to setup a Fibonacci function and I want the input to be an integer array of indeterminate length and it's output to be an integer array of 1+ the length of the first.
I have tried just not typing it at all and running
nFibbo x = x ++ sum x
But that shows up with a different error "cannot construct the infinite type: a ~ [a]"
Well that's quite weird, since:
if x is an array [a], then sum x will be an a. The (++) :: [a] -> [a] -> [a] function takes two lists, not a list and an element.
You can however construct a list with one element, for instance using list syntax:
nFibbo :: Num x => [x] -> [x]
nFibbo x = x ++ [sum x] -- list with one element
Note that here you will add the sum of all previous elements as last element. Not the sum of the last two elements (like Fibonacci usually does).
You also need to add a Num x type constraint, otherwise the type of elements of the list is not per se a numerical type, and thus you can not calculate the sum of these numbers.
I'm trying to create a function that eliminates multiples of a given Integer from a list of Integers, in the form multiples x [y], where x is the given Integer, and y is the list.
Here's what I have:
multiples :: Integer -> [Integer] -> [Integer]
multiples a [] = []
multiples a [b] = filter (\l -> l `mod` a /= 0) [b]
multiples will fail when called, saying "Non-exhaustive patterns in function multiples". So I used ghci -Wall with my file to see what patterns were missing, and it returns this:
multiples.hs:2:1: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for `multiples': Patterns not matched: _ (_:_:_)
multiples.hs:2:11: warning: [-Wunused-matches]
Defined but not used: `a'
I get the feeling I'm missing something really simple with line 2, but I'm a bit stuck. What am I doing wrong?
Welcome to Stack Overflow! There are a couple of things to fix in your function, but I'll start with the one you seem the most confused about: here [b] is a pattern matching a one-element list, naming its single item b. ([b, c] would be a pattern matching a two-element list, etc.) It's not a pattern matching an arbitrarily long list of bs. GHC is telling you off because you haven't accounted for the case where the function has been given a two-or-more-element list.
If you want to match an arbitrary list of bs, omit the square brackets. Additionally, the first line of your function is not necessary because the second line already deals with that case.
multiples :: Integer -> [Integer] -> [Integer]
multiples a bs = filter (\b -> b `mod` a /= 0) bs
Or, using a list comprehension,
multiples :: Integer -> [Integer] -> [Integer]
multiples a bs = [b | b <- bs, b `mod` a /= 0]
Two more things: I'd name this function withoutMultiples because it filters out multiples of a, and because Haskell functions are curried by default you can omit the bs in the filter version.
withoutMultiples :: Integer -> [Integer] -> [Integer]
withoutMultiples a = filter (\b -> b `mod` a /= 0)
Your pattern
multiples a [b]
expects an Integer (bound to name "a") and list of Integer containing one element (bound to name "b"). Remove square brackets (which will change type of "b" to [Integer]) in this pattern and it should be working. Also you can curry this function to form
multiples a = filter (\l -> l `mod` a /= 0)
and omit first pattern as it should be covered by filter function.
selectMenu :: Int->IO()
selectMenu num
|(num==2)=convertBinToDecimal
convertBinToDecimal:: IO()
convertBinToDecimal= do
putStrLn("\n\tConvert Binary To Decimal\n")
putStrLn("----------------------------------------------------------\n")
putStrLn("Enter 5 binary numbers [,,] : ")
input<-getLine
let n=(read input)::Int
--putStrLn (show n)
let result = convertionTO binaryToDec n
putStrLn(show result)
this code seems fine.but there is an error.
Any solutions to fix this error?
Thank you
You're trying to use reverse on x, which is an Int (since it's the argument of binaryToDec, which you have given the type Int -> Int), but reverse has the type [a] -> [a], so it only works on lists.
This is basically what the compiler means when it says "cannot match expected type [a] with actual type Int in the first argument of reverse". It's a good idea to read the error messages carefully, they often provide good clues to what is wrong.
To fix this, you probably want to convert x to a list somehow, or change the function to take a list instead.
Like hammar said you cannot reverse Int. You need to convert your number to list somehow with :: Int -> [Int]
Here is some kludges to do that.
listToNum :: [Int] -> Int
listToNum = foldl1 ( (+) . (*10) )
numToList :: Int -> [Int]
numToList n | n <= 9 = [n]
| otherwise = numToList (n `div` 10) ++ [n `mod` 10]
And then you can use it like reverse $ numToList x instead of reverse x.
And just a note. Your selectmenu function did not matches all possible cases. What if num is not equal to 2?