Couldn't match type ‘a’ with ‘Int’ in Haskell - haskell

place n x is meant to find the place of integer n in the list x, for example place 2 [1,2,3] will return 1:
place :: Int -> [a] -> Int
place n x = length $ takeWhile (/=n) x
But it gets the error Couldn't match type ‘a’ with ‘Int’
Why? takeWhile should return a list and its length is an integer, hence place should output an Int eventually.

The correct type signature for place is:
place :: Int -> [Int] -> Int
When you use [a] in place of [Int] you are saying that place will work on a list of any type. For instance, I could call it like this:
place 3 [True, False, False, True]
or call it with a list of Char:
place 4 "this is a test"
But neither of these can work because takeWhile will compare each element of the list against the Int n. This forces the list to be a list of Ints.

You are using (/=) :: Eq ty => ty -> ty -> Bool where that second ty ~ Int due to the type of n. If ty is Int then the type of the other argument of (/=) (x) must be Int too.

find the place of integer n in the list x
ah, but there are no integers in the list at all. The type is [a]. Only if the type were [Int] would it be possible to find an n in it.
Now, you might say “[Int] is a possible instantiation of [a], so it could still work in that case”. Well, it could – but only in that case, and therefore it would be stupid not to enforce a ~ Int in the type signature.
More reasonably, you might want to find any type of number which happens to be equal to the integer n. Well, you can do that:
place' :: (Num a, Eq a) => Int -> [a] -> Int
place' n = length . takeWhile (/= fromIntegral n)
Here, I first convert n to the type of number that's contained in the list, and then compare it with those numbers.

Related

Couldn't match type 'b' with Int

Task: Transform a list of numbers using map so every even number gets divided by 2 and every odd number gets multiplied by 2
prel2 :: (Fractional b) => [Int] -> [b]
prel2 x = map prel x
where prel y
|even y = y/2
|otherwise = y*2
I know this is some basic stuff, but I can't figure out why the error is raised
Your type signature promises that you can provide a list of values of any type that has a Fractional instance. But, since y is always an Int (since x :: [Int]), then y*2 will always be an Int, and y/2 wouldn't type-check at all.
What you probably want is to use div instead of / to replace the Fractional constraint with an Integral constraint, then generalize your type to Integral b => [b] -> [b].

Syntax in Functions (Expected kind `* -> Constraint', but `Int' has kind `*') [duplicate]

This question already has answers here:
`String' is applied to too many type arguments
(2 answers)
Closed 2 years ago.
I'm starting to learn Haskell and I'm struggling with syntax in Functions. I'm trying to create a function that receives a Number 'e' and a Number 'n', returning a list with of 'n' times 'e'.
Example: repn 3 5 would return [3,3,3,3,3]:
repn :: Int a => a -> a -> [a]
repn e n
| n >= 1 = (take n (repeat e))
| otherwise = []
But I'm getting this error:
* Expected kind `* -> Constraint', but `Int' has kind `*'
* In the type signature: replica :: Int a => a -> a
As a rule of thumb, writing something of the form Foo a => ... only makes sense of Foo is a type class. Unlike in OO languages, a class and a type in Haskell are completely different things. Int is a type, therefore it cannot be used in this way; instead you should simply use
repn :: Int -> Int -> [Int]
...though actually there's no reason to restrict the list-element type at all, the signature could as well be
repn :: a -> Int -> [a]
Alternatively, you can use a type class: the class of “int-like types” is Integral. Then you can't use take directly, as that is restricted to Int for the counter argument; however you can convert any integral type to Int:
repn :: Integral n => a -> n -> [a]
repn e n = take (fromIntegral n) $ repeat e
-- Note no case distinction is needed, because `take` already yields
-- an empty list if `n<1`.
Your type definition is not correct. The double arrow is used to show required typeclasses (aka kind * -> Constraint), or a constraint on types. However, Int is itself a type (aka kind *).
You can't specify types in this way. In your implementation, n must be an Int, but e could be anything. Since you specify that it should be a number, though, you can constrain it with the Num typeclass. The correct version of your signature therefore is:
repn :: Num a => a -> Int -> [a]
If you want e to be constrained to an Int, then your signature should be
repn :: Int -> Int -> [Int]
If you don't need any constraints on e, your signature can be
repn :: a -> Int -> [a]
These are all valid type signatures for the function you have written. (Though in actual code, I would just point you to the builtin replicate function.)

Check if a string contains a certain character

I need to check if my string contain a specific character.
I tried this:
charFound :: Char -> String -> Bool
charFound c s = filter(\x -> x == c) s
But it gives me:
Couldn't match expected type Bool with actual type [Char]
I know that filter:
returns a list constructed from members of a list (the second argument) fulfilling a condition given by the first argument.
How could I reach the goal and return a bool instead of a list?
For your purpose, you could use the function elem :: Eq a => a -> [a] -> Bool from prelude. It does exactly what it says on the label. To implement this function, I would use something like this:
elem = any . (==)
or even more elementary:
elem x = foldr ((||) . (x ==)) False
Notice that due to the short-circuit behaviour of (||) this also works with infinite lists as long as x is found.
The type of filter is (a -> Bool) -> [a] -> [a].
You have supplied the first argument which has type Char -> Bool (which is correct), then the second argument which is String (that's [Char]) which is correct, so the type of filter (\x -> x == c) s is [Char].
But the type signature you have provided says the function returns a Bool, which doesn't match the actual type returned.
You probably want to use any instead of filter. It's type is (a -> Bool) -> [a] -> Bool.
There's also an all function that returns True if and only if all elements of the list satisfy the predicate passed. You may also consider the functions or and and that given a [Bool] compute the disjunction or conjunction of the values. So any f = or . map f and all f = and . map f.
For all list-related functions see the Data.List module.

Couldn't match expected type error

As a beginner, I was working on item number 3 of the Haskell 99 problems. The first code snippet is my solution. However, I cannot add the type declaration of [a] -> Int -> a.
It produces an error: Couldn't match type 'a' with 'Int'
--My Solution
--elementAt :: [a] -> Int -> a
elementAt xs num = head . reverse $ takeWhile (<num+1) xs
Meanwhile, one of the solution in the problem 3 works perfectly with the same output.
elementAt' :: [a] -> Int -> a
elementAt' list i = list !! (i - 1)
I've used the :type in the GHCI for the elementAt without the declaration and it shows:
elementAt :: (Num c, Ord c) => [c] -> c -> c
What is the difference of the two functions?
takeWhile (<num+1) xs says that you want to take elements at the front of the list xs while the element (not the index!) is less than num + 1. Since you're comparing num (which is an Int) with the list elements, the compiler infers that the list elements have to be Int as well, which contradicts your type declaration.
Without the type declaration, GHC infers that xs's elements and num have to be the same type (since you compare list elements with num). This type has to have an Ord instance (for the comparison) as well as a Num instance (because of the addition).
The type of takeWhile (< num + 1) is [Int] -> [Int].
However the type of xs is [a].
Essentially you are trying to apply a predicate Int -> Bool to elements of type a.
If you want to filter based on the position in the list, you first need to augment the input list with the position of each element. You can do this fairly easily with zip:
zip xs [1..]
You can then drop elements based on the value of the second element of the resulting list.

Converting types in Haskell

I'm working on a conversion problem for homework, and am a complete Haskell newbie, so bear with me. On one of them, it asks us to attempt to get the type of a function to be:
fc :: (Bool, [Char]) -> Int -> Integer -> [Bool]
Without worrying about what the actual function does or anything. These functions will not be run, it is just a test to see if we can convert types correctly. So far the furthest I can get is this:
fc :: (Bool, [Char]) -> Int
fc (x, y) = ord (head y)
Where I am turning it into an Int. When I try to turn it into an Integer using the toInteger function, it gives me:
Couldn't match expected type `Int -> Integer'
with actual type `Integer'
In the return type of a call of `toInteger'
Probable cause: `toInteger' is applied to too many arguments
In the expression: toInteger (ord (head y))
Any tips for the new guy?
Edit:
What I have been trying, for reference, is:
fc :: (Bool, [Char]) -> Int -> Integer
fc (x, y) = toInteger (ord (head y))
And I am getting the error above.
Your type signature is wrong. If you convert something you can't write it into the type signature. Only the last one is the return type. The others are parameter types.
Follow these:
fc::(Bool,[Char])->Integer
fc (x,y) = toInteger . ord . head $ y
fc::(Bool,[Char])->Int->Integer--
fc (x,y) n = if n == w then n else w
where w = toInteger . ord . head $ y
Edit:
The others mentioned currying what is absolutely correct if your teacher expect it. But the conversions doesn't take place in the type sign.
As n.m. says, the idea this is getting at is called currying. Basically, in Haskell, any function takes a single value and returns a single value: a -> b.
So, given this restriction, how can we implement functions like addition, which need two parameters? The answer is that we implement a function which takes a number, and returns another function which takes a number and returns a number. Laying it out this way might clarify things:
add :: Int -> Int -> Int
add x = f where f y = x + y
(which is equivalent to add x y = x + y, as well as add = (+)).
In your case, you should read the error carefully: Couldn't match expected type Int -> Integer with actual type Integer In the return type of a call of toInteger means that Haskell is expecting fc to return a value of type Int -> Integer, because that's what your type signature says, but the definition you've provided will always produce a value of type Integer.

Resources