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.
Related
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
insert_at insert an element e into a list xs in specific location n
testgetting Left if n less than 0
test2 getting Left if n larger than xs's length or The type e isn't match the element's type in listxs. Otherwise passing Right xs to the next.
import Data.Typeable
insert_at :: a -> [a] -> Int -> [a]
insert_at e xs n = a++(e:b) where
t = splitAt n xs
a = fst t
b = snd t
test :: (Ord a, Num a) => b -> a -> Either [Char] b
test xs n = if n < 0 then Left "n<0" else Right xs
test2 :: (Typeable a1, Typeable a2) =>
a1 -> [a2] -> Int -> Either [Char] [a2]
test2 e xs n
| n> ( length xs )= Left "n> $ length xs "
| (typeOf e) /= (typeOf (head xs) ) = Left "(typeOf e) /= (typeOf (head xs) ) "
|otherwise = Right xs
sf :: Typeable a => a -> [a] -> Int -> Either [Char] [a]
sf e xs n = test xs n >>test2 e xs n >> Right (insert_at e xs n)
All the other error got properly handled, expect this.
* No instance for (Num Char) arising from the literal `1'
* In the expression: 1
In the second argument of `sf', namely `[1, 2, 3, 4, ....]'
In the expression: sf 'a' [1, 2, 3, 4, ....] 3
The error message states that you're trying to evaluate the expression sf 'a' [1, 2, 3, 4, ....] 3. Since this expression is not shown in your question, I'm assuming you're using it in GHCi to test out your code, right?
The type signature of sf says that the first parameter has type a, and the second parameter has type [a], which is a list whose elements are of the same type as the first parameter.
So the compiler sees that the first parameter is 'a'. That's a character, type Char.
"Got it," - thinks the compiler, - "now I know that a is Char. And now I know that the second parameter must have type [Char] - that is, a list of Char".
And yes, the second parameter is indeed a list, but wait! The first element of the list is not a character, but number 1! That does not compute!
Fortunately, number literals are special in Haskell. Number literals are not merely of type Int or even of type Integer, no! Numbers can be of any type as long as that type has an instance of class Num.
So since the compiler already knows that the elements of that list must be of type Char, but it sees a number literal, it concludes that it must now find an instance of class Num for type Char.
But there is no such instance! And so the compiler rightly complains: "no instance Num Char"
To fix the problem, I need to better understand what you were actually trying to do.
Did you intend the whole function to work on numbers? Then the first parameter must be a number, not a character.
Or did you intend it to work on characters? Then the second parameter must be a list of characters, not numbers.
Or did you intend the first two parameters not to be the same type at all? Then you must change the type signature of sf to indicate that.
sf expects a value and a list as its first two arguments. The elements of the list must have the same type as the first argument. This is the meaning of
sf :: a -> [a] -> ...
When you write sf 'a' [1], this means 1 and 'a' must have the same type. So the type checker looks for a way to interpret 1 as a Char; it fails, because this is not possible. Some fixes might include:
sf 'a' "1234" 3
sf 'a' [toEnum 1, toEnum 2, toEnum 3, toEnum 4] 3
sf (fromEnum 'a') [1, 2, 3, 4] 3
I'm just learning haskell (on my own, for fun) and I've come up against a wall.
My Question:
How can I define a function
flrt = (floor . sqrt)
When I try it in a file and compile, GCHi complains with the following:
AKS.hs:11:9:
No instance for (RealFrac Integer)
arising from a use of `floor'
Possible fix: add an instance declaration for (RealFrac Integer)
In the first argument of `(.)', namely `floor'
In the expression: (floor . sqrt)
In an equation for `flrt': flrt = (floor . sqrt)
AKS.hs:11:17:
No instance for (Floating Integer)
arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Integer)
In the second argument of `(.)', namely `sqrt'
In the expression: (floor . sqrt)
In an equation for `flrt': flrt = (floor . sqrt)
I don't understand why the resulting function isn't just Int -> Int.
I've just finished my second year of CS and done a basic PL course. I've heard of, but don't quite get types yet. I tried reading through a few haskell tutorials but it's all going above my head.
P.S. - I also don't understand what a monad is. (a lot of the other questions that my search turned up talked about these)
P.P.S. - My full source
bar = \a b -> if (2^a) > b
then (a-1)
else bar (a+1) b
foo = bar 1
flrt :: Integer -> Integer
flrt = (floor . sqrt)
aks target = if (target < 2)
then putStr "Not a Prime.\n\n"
else if elem (mod target 10) [0,2,4,5,6,8]
then putStr "Composite\n\n"
else if (elem target) [a^b | a <- [3,5..(flrt target)], b <- [1.. (foo target)]]
then putStr "Composite\n\n"--}
else
putStr "filler"
The problem is that you're trying to use Integer as the input. Haskell is strongly typed, which means there are no implicit coercions or conversions of any kind. Look at signatures of functions you're trying to compose:
sqrt :: Floating a => a -> a
floor :: (RealFrac a, Integral b) => a -> b
And at the signature of your function inferred by GHC:
> :t floor . sqrt
floor . sqrt :: (RealFrac b, Integral c, Floating b) => b -> c
So, to have a function that goes from Integer (which doesn't have a Floating instance) to Integer, you have to first convert your argument to Floating, which can be done by using fromIntegral:
> :t floor . sqrt . fromIntegral
floor . sqrt . fromIntegral :: (Integral a, Integral c) => a -> c
As copumpkin remarked, it might actually be a bad idea to convert to floating point here, because this comes with loss of precision and therefore might, even with rounding, yield incorrect results for sufficiently large integer inputs.
I assume all numbers you're dealing with will at least be small enough that there is some floating-point representation for them, e.g. all are < 10300. But, for instance
Prelude> round(sqrt.fromInteger$10^60 :: Double) ^ 2
1000000000000000039769249677312000395398304974095154031886336
Prelude> {- and not -} 10^60 {- == (10^30)^2 == (sqrt$10^60) ^ 2 -}
1000000000000000000000000000000000000000000000000000000000000
Which is way off, in terms of absolute difference. Still it's certainly a rather good approximation relative to the numbers themselves, so you can use it as a quickly determined starting point for an algorithm to find the exact result. You can implement Newton/Raphson (in this case AKA Heron) with Integers:
flrt :: Integer -> Integer -- flrt x ≈ √x, with flrt x^2 ≤ x < flrt(x+1)^2
flrt x = approx (round . (sqrt::Double->Double) . fromInteger $ x)
where approx r
| ctrl <= x, (r+1)^2 > x = r
| otherwise = approx $ r - diff
where ctrl = r^2
diff = (ctrl - x) // (2*r) -- ∂/∂x x² = 2x
a//b = a`div`b + if (a>0)==(b>0) then 1 else 0 -- always away from 0
This now works as desired:
*IntegerSqrt> (flrt $ 10^60) ^ 2
1000000000000000000000000000000000000000000000000000000000000
The division always away from 0 in the Newton-Raphson correction is here necessary to prevent getting stuck in an infinite recursion.
I have a function that works fine:
z::Int->Int->[Char]
z x y =show(x)++show(y)++show(x*y)
It's really just a function that convert some numbers into a string.
Then I quicksort the string with my quick sort function.
quicksort.z 2 3
but here I get the error
Couldn't match expected type `a0 -> [a1]' with actual type `[Char]'
In the return type of a call of `z'
In the second argument of `(.)', namely `z 2 3'
In the expression: flagskib . z 2 3
I tried fixes like parentheses and use of the $ function, but no help.
I appreciate any words on it. The problem is already fixed so the whole meaning of this post is to learn.
quicksort takes one argument. z takes two. The composition operator has the following type
(.) :: (b -> c) -> (a -> b) -> a -> c
Perhaps you can see the problem now. The types do not match up.
quicksort $ z 2 3
Will work. So will quicksort . z 2 $ 3 or similarly (quicksort . z 2) 3 because the application of z to the argument 2 returns a function of one argument, which matches the type of (.) (partial application).
I'm assuming quicksort has type[a] -> [a].
(.) is used for function composition, thus it expects two functions to compose but you use a [Char] instead. What you wrote is equivalent to \x -> quicksort ((z 2 3) x), which obviously doesn't work.
You should use ($) instead, right-associative function application: quicksort $ z 2 3, equivalent to quicksort (z 2 3).
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]