sum of elements multiplied by 3 in haskell - haskell

I want to create a function which takes an n elements long list and returns sum of all elements multiplied by 3. The way I do it is here:
times3::Int->Integer
times3 x = sum [map (3*) [1..x]]
This code however results in the following error:
Couldn't match expected type `Integer' with actual type `[Int]'
Do you have any idea why is this happening?

[map (3*) [1..x]] is a list of length one, since [ some expression here ] is always a singleton list. In your code it's the list-of-lists [[3,6,...,3*x]] of type [[Int]] as the compiler reported.
Your type signature claims the result is Integer, and to obtain that, we would need to start with list of type [Integer]. The compiler checks the type equality [[Int]] ~ [Integer] and complains that [Int] is not Integer, hence the type error.
Instead, (map (3*) [1..x]) is a list of length x, namely [3,6,...,3*x], which is of type [Int]. This is the list I think you intended to use.
Since this list is not a [Integer], you either have to perform a conversion using fromIntegral or, more simply, to change your type signature in the function.
Another alternative would be to make the argument x an Integer.

#chi's answer explains what the problem is with the current implementation. The only thing I want to add is that the sum of *3, 6, 9, …, 3×n; can be determined without enumerating over a list. Indeed the sum:
n n
--- ---
\ \
/ 3 i = 3 / i
--- ---
i=1 i=1
the sum if 1, 2, …, n can be calculated with n×(n+1)/2, so we can calculate the sum with:
times3 :: Int -> Integer
times3 n = 3 * div (n * (ni+1)) 2
where ni = fromIntegral n
or without converting an Int to Integer and for any Integral type:
times3 :: Integral i => i -> i
times3 n = 3 * div (n * (n+1)) 2

Related

Haskell: Couldn't match expected type

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.

Haskell length list + factorial

I'm very new to Haskell. I've been trying to implement n_choose_r but for some reason my factorial function is returning strange values.
Main.hs
factorial 0 = 1
factorial n = n * factorial (n-1)
subsets k list = factorial n where
n = length list
some different cases
> subsets 3 [1..4]
24 // correct value
> factorial 60
8320987112741390144276341183223364380754172606361245952449277696409600000000000000
> subsets 3 [1..60]
-8718968878589280256 // wrong value
> subsets 3 [1..100]
0 // wrong value
It seems the numbers get wonkier the longer the list. Can anyone explain?
Your factorial function is polymorphic: it has type (Eq p, Num p) => p -> p. When you just call it like factorial 60, p gets instantiated as Integer (this choice is called "type defaulting"), which is arbitrary-precision and has no upper bound. However, length is not polymorphic in its output: it always returns an Int. Haskell won't automatically convert between numeric types for you, so when you call factorial with the result of length, it uses Int too, which does have an upper bound, which in your case appears to be 9223372036854775807 (which you can verify by doing maxBound :: Int). To work around this problem, you can either convert from Int to Integer yourself:
subsets k list = factorial (toInteger n) where
n = length list
or use genericLength, which is the same as length except for being polymorphic in its output type:
import Data.List
subsets k list = factorial n where
n = genericLength list
Note that if you use the latter option, you need to be careful not to do anything else that would force use of Int instead of defaulting to Integer.

Haskell beginner: "No instance for...arising from..." error

My goal is to write a function that calculates the maximum Collatz number below a certain number 'n'. (It's a Project Euler question for those who are familiar.)
Some context: A Collatz number for a given integer is equal to the length of the Collatz sequence for that integer. A Collatz sequence for an integer is calculated as follows: the first number ("n0") in the sequence is that integer itself; if n0 is even, the next number in the sequence ("n1") is equal to n / 2; if n0 is odd, then n1 is equal to 3 * n0 + 1. We continue recursively extending the sequence until we arrive at 1, at which point the sequence is finished. For example, the collatz sequence for 5 is: {5, 16, 8, 4, 2, 1} (because 16 = 3 * 5 + 1, 8 = 16 / 2, 4 = 8 / 2,...)
I'm trying to write a function ("maxCollatzUnder") which, when passed an integer "m", returns the integer (less than or equal to m) which has the longest Collatz sequence (i.e., largest Collatz number). For example, maxCollatz 20 (i.e., what integer below (inclusive) 20 has the longest collage sequence?) should return 19 (the number 19 has a Collatz sequence of length 21: [19,58,29,88,44,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]).
In the code below, the "collatz" and "collatzHelper" functions compile and run correctly. I'm having trouble with the "maxCollatzUnder" function. This function intends to (I) create a list of 2-tuples (x,y) for each integer x ranging from 1 to m (where m is the function argument) and where where y represents the Collatz number for integer x and then (II) look through the list for the highest Collatz number (i.e., y) and return its associated integer (i.e., x)
maxCollatzUnder n = foldl(\acc (i,j) -> if j > acc then i else acc) 0
(zip [1..n] ( map collatzLength [1..n]))
where collatzLength n = length . collatz $ n
collatz n = map truncate $ collatzHelper n
collatzHelper 0 = [0]
collatzHelper 1 = [1]
collatzHelper n
| (truncate n) `mod` 2 == 0 = [n] ++ collatzHelper (n/2)
| otherwise = [n] ++ collatzHelper (3*n+1)
I get the following error when I (attempt to) compile.
*Main> :l PE14Collatz.hs
[1 of 1] Compiling Main ( PE14Collatz.hs, interpreted )
PE14Collatz.hs:7:89:
No instance for (RealFrac Int)
arising from a use of `collatzLength'
In the first argument of `map', namely `collatzLength'
In the second argument of `zip', namely
`(map collatzLength [1 .. n])'
In the third argument of `foldl', namely
`(zip [1 .. n] (map collatzLength [1 .. n]))'
Failed, modules loaded: none.
What's curious is that the code compiles and runs correctly if I change the "maxCollatzUnder" to the following code (see below). The only change is that, in the version below, the fold function returns "j" (i.e., the largest Collatz number) instead of "i" (i.e., the integer which generates the largest Collatz number).
maxCollatzUnder n = foldl(\acc (i,j) -> if j > acc then j else acc) 0
(zip [1..n] ( map collatzLength [1..n]))
where collatzLength n = length . collatz $ n
Suggestions on a more efficient/elegant approach are welcome though I would still be interested in understanding the cause of this error.
Because of your use of truncate (a method of RealFrac) and / (a method of Fractional, a superclass of RealFrac), Haskell infers the following two type signatures for your last two functions:
collatz :: (RealFrac a, Integral b) => a -> [b]
collatzHelper :: RealFrac a => a -> [a]
Haskell then tries to deduce the type of maxCollatzUnder, and its thought process goes like this:
"In collatzLength n = length . collatz $ n, we're passing n to collatz, so the argument to collatzLength must be a RealFrac."
"Therefore, in map collatzLength [1..n], [1..n] must be a list of RealFrac values."
"Therefore, the n in map collatzLength [1..n] must be a RealFrac type."
"Therefore, the n in zip [1..n] (which is the same n) must be a RealFrac type, and so [1..n] is a list of RealFracs."
"Therefore, the i in (\acc (i,j) -> if j > acc then i else acc) must be a RealFrac."
"Because the aforementioned lambda can return either i or acc, they must be the same type."
"Because j is being compared to acc, j must be the same type as acc — and thus the same type as i and a RealFrac."
"But wait— j is the return value from collatzLength, which is the return value of a call to length, and so it has to be an Int, but Int isn't in RealFrac!"
"ERROR! ERROR!"
I have to go now (the Compiler Cabal doesn't like me giving away their secrets), but the shortest fix is to not use truncate and / and just use div for (floored) integer division.

Number of elements in list bigger than average

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]

Problems obtaining the list of divisors of a number in Haskell

This is not a duplicate question. Read below...
I'm declaring the following function:
divisors x = [(a, x/a) | a <- [2..(sqrt x)], x `mod` a == 0]
What I want to obtain is the divisors of x: A list of tuples that will contain (n, k) such as n * k = x
Example:
> divisors x
[(1,10), (2, 5)]
Why the above code isn't working?
It gives me the error:
*Main> divisors 10
<interactive>:1:0:
Ambiguous type variable `t' in the constraints:
`Floating t'
arising from a use of `divisors' at <interactive>:1:0-10
`Integral t'
arising from a use of `divisors' at <interactive>:1:0-10
Probable fix: add a type signature that fixes these type variable(s)
I've tried manually setting the signature of the function without success...
The problem is sqrt returns a Floating a, and you really just want integers when finding divisors. You can turn a Floating a into an Integral a with ceiling, floor or round. I will use ceiling, as I'm not sure if using floor or average won't skip a divisor.
The sqrt function also only accepts a floating number, so you will have to convert an integer into a floating before giving it to it (this can be done with fromIntegral).
Also, you use /, which also works with floating numbers. Using div is better as it works with integral numbers (rounding when necessary).
divisors x = [(a, x `div` a) | a <- [2..(ceiling $ sqrt $ fromIntegral x)], x `mod` a == 0]
With this, divisors 10 will give [(2,5)] (your code stops the (1,10) case from happening - I'm guessing this was intentional). Unfortunately you will get duplicates, eg divisors 12 will return [(2,6),(3,4),(4,3)], but that shouldn't be too hard to fix if it is a problem.
You can see the problem if you ask for the type:
divisors :: (Integral t, Floating t) => t -> [(t, t)]
and then check what things are both Integral and Floating:
Prelude> :info Floating
class Fractional a => Floating a where
instance Floating Float -- Defined in GHC.Float
instance Floating Double -- Defined in GHC.Float
and
Prelude> :info Integral
class (Real a, Enum a) => Integral a where
instance Integral Integer -- Defined in GHC.Real
instance Integral Int -- Defined in GHC.Real
so, it can be neither Int, Integer, Float or Double. You're in trouble...
Thankfully, we can convert between types, so that while sqrt needs a Floating, and mod needs an Integral (btw, rem is faster), we can either, e.g., do away with floating point division:
divisors :: Integer -> [(Integer, Integer)]
divisors x = [(a, x `div` a) | a <- [2..ceiling (sqrt (fromIntegral x))], x `rem` a == 0]
> divisors 100
[(2,0),(4,0),(5,0),(10,0)]
However, you need to think hard about what you really mean to do when converting integer types to floating point, via sqrt...
In Haskell, integer division and fractional division are different operations, and have different names. The slash operator, /, is for fractional division. Integer division is accomplished with div or quot (the difference between the two having to do with the behavior when there are negative numbers involved).
Try replacing x/a with
x `quot` a
instead.
The compiler error tells you exactly this: that you're treating a type sometimes as an integral number (by using mod), and sometimes as a fractional number (by using /), and it's not sure how to pick a type that acts like both of those.
You'll have a similar issue with sqrt, once that's sorted, though. There again, you need to be consistent about whether your types are integers or (in that case) floating point. For the purpose of finding possible divisors, it should suffice to range up to the greatest integer less that the floating point, so consider using floor (sqrt (fromIntegral x))). The fromIntegral converts x (which must have an integral type) to a different type -- in this case, it will default to Double. The floor then converts the Double result back into an integral type.
Instead of taking the square-root to bound the search, you can allow the comprehension to range over an infinite list, and use takeWhile to stop the search when the remainder is greater than the divisor:
divisors x = takeWhile (uncurry (<=)) [(a, x `div` a) | a <- [1..], x `mod` a == 0]
> divisors 100
[(1,100),(2,50),(4,25),(5,20),(10,10)]
Note: your original example shows (1,10) as one of the divisors of 10, so I started the comprehension from 1 instead of 2.
Hmm, this does search beyond the square-root until it hits the next factor above.
How about this:
divisors x = [(a, x `div` a) | a <- takeWhile ((<= x) . (^2)) [1..], x `mod` a == 0]

Resources