Can't compile because of types when using nub, map and take - haskell

I've got this simple function:
bombplaces::Int->[(Int,Int)]->[(Int,Int)]
bombplaces bombCount listOfPossiblePoints = nub (map (take bombCount) (perms listOfPossiblePoints))
bombs are (x,y) (carthesian points)
i need to get an all permutations and take only first few (bombCount) points.
I'm getting following error:
Couldn't match expected type `(Int,Int)' with actual type `[a0]'
Expected type: [a0] -> (Int,Int)
Actual type: [a0] -> [a0]
In the return type of a call of `take'
In the first argument of `map', namely `(take liczbaBomb)'

If you remove the type signature and ask GHCi for the type, your problem will be obvious:
> :t bombplaces
bombplaces :: Eq a => Int -> [a] -> [[a]]
That is, bombplaces wants to return a list of lists whereas you want it to return a plain list. You need to either change the type signature, or change the definition of the function, depending on what you want the behaviour to be.
N.B. You didn't tell us what definition of perms you are using, so I assumed the obvious one.

Related

Misunderstandment of map parameters in Haskell

I'm trying to create a function, which will multiply each element in a list called s by a parameter x.
First, I experimented around in ghci and found that fn1 s = map (* 2) s works. The I tried to make the function more general by including the factor x as a parameter fn2 x s = map (* x) s. However this leads to an error, when I call the function:
<interactive>:12:1: error:
• Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. (Num a, Num [a]) => [[a]] -> [[a]]
After some additional experimentation I found that I can solve the problem by surrounding the * operator with ()
fn3 x s = map ((*) x) s
What I need help with is why the latter piece of code works while the previous does not.
Any help is appreciated.
This would happen if you forget to provide the x parameter when calling fn2, for example:
> fn2 [1,2,3]
The compiler sees [1,2,3] where x should be, and it also sees (* x) in the body of the function, and it reckons that [1,2,3] must be a valid argument for operator *. And since operator * is defined in type class Num, the compiler infers that there must be an instance Num [a] - which is exactly what it says in the error message.
The result of such call would be another function, which still "expects" the missing parameter s and once given it, will return a list of the same type as s. Since it's clear from the provided arguments that x :: [a], and you're using map to transform x to the same type, the compiler infers that s :: [[a]], and so the result of calling fn2 like that is [[a]] -> [[a]], which is what the error message says.
Now, the requirement of an instance Num [a] in itself is not a big deal. In fact, if you enable the FlexibleContexts extension (as the error message tells you), this particular error goes away, and you will get another one, complaining that there is no instance Num [a] for any a. And that is the real problem. There is no instance Num [a], because, well, lists are not numbers.

What are the Function types

The question is to determine function type of this : second xs = head (tail xs)
I tried everything
:t second gives me:
*Main> :type second
second :: [a] -> a --- is this the function type?
,then I tried :type second; :type "second xs = head (tail xs)".
It still does not work. How to determine Function type using Haskell
As you already know, you can use GHCi to find the type of a Haskell identifier by using the :type command (or its shorter version :t). In this case, GHCi gives you the answer second :: [a] -> a. The :: symbol means 'type-of', so this answer is just GHCi's way of telling you that 'the type of second is [a] -> a'.
But there's still another question here: what does this type mean? Well, let's pull it apart:
Any type of the form x -> y is the type of a function which takes as input one parameter of type x, and returns a value of type y.
In this case, we have a type [a] -> a, so the input type is [a] (i.e. a list of values of type a), and the output type is a (i.e. a single value of type a).
Thus, the statement second :: [a] -> a means that second is a function which takes as input a list of as, and gives as output a single value of the same type a. This ties in with what we know of the function: given a list, it returns a single value from that list.
EDIT: As #chepner pointed out in the comments, it is important to realise that a is a stand-in for any type. The only constraint is that, if the input is a list of as, then - no matter what a is - the return type must also be of type a. (This sort of indeterminate type is called a type variable.)

read::Int not working in Haskell in example

Here is the problem. It looks simple yet
main = do
s <- getContents
let list = map (read::Int) (words s)
print list
Couldn't match expected type `Int' with actual type `String -> a0'
Probable cause: `read' is applied to too few arguments
In the first argument of `map', namely `(read :: Int)'
In the expression: map (read :: Int) (words s)
The problem was that I thought :: is like casting and I have to put the return type. The solution was to add full wanted |function signature instread.
read is a function (of type Read a => String -> a), so it can't have type Int. You could do read :: String -> Int, or you could put a type signature on list rather than read, so you get:
let list :: [Int]
list = map read (words s)

Infinite Square Roots : Couldn't match expected type & cannot construct the infinite type

Sorry for what's probably an idiot question - trying to learn Haskell at the moment;
I'm trying to build a basic function that will create an infinite list of square roots on a number, so I can get practice with the take function and how it works.
I wrote the following code;
infisqrt x = infisqrt'((x :: Float) [])
-- helper method
infisqrt' x xs = infisqrt'(sqrt(x) (xs ++ [(sqrt(x))]))
However, this is returning with two errors when trying to load the library;
:l isq
isq.hs:1:24:
Couldn't match expected type ‘[t0] -> a’ with actual type ‘Float’
Relevant bindings include
infisqrt :: Float -> [a] -> t (bound at isq.hs:1:1)
The function ‘x :: Float’ is applied to one argument,
but its type ‘Float’ has none
In the first argument of ‘infisqrt'’, namely ‘((x :: Float) [])’
In the expression: infisqrt' ((x :: Float) [])
isq.hs:5:33:
Occurs check: cannot construct the infinite type: a ~ [a] -> a
Relevant bindings include
xs :: [a] (bound at isq.hs:5:13)
x :: a (bound at isq.hs:5:11)
infisqrt' :: a -> [a] -> t (bound at isq.hs:5:1)
In the first argument of ‘sqrt’, namely ‘(x)’
In the first argument of ‘infisqrt'’, namely
‘(sqrt (x) (xs ++ [(sqrt (x))]))’
Can anyone let me know where I'm going wrong with this?
Haskell function invocation doesn't use parentheses. It looks like you're expecting this:
infisqrt x = infisqrt'((x :: Float) [])
to mean "pass x and [] as arguments to inifsqrt." However, to the compiler, it actually means "pass [] as the first argument to x, and then pass the result to infisqrt'." If you take the extra parentheses out, you should start getting traction:
infisqrt x = infisqrt' (x :: Float) []
(remember, you've got the same thing going on in infisqrt''s definition)
As a side note, it's typically preferable to put arguments' types in a function type declaration:
infisqrt :: Float -> [Float]
infisqrt x = infisqrt' x []

Typecheck weirdness with lists of lists

I am not a Haskell pro. Today I had a somewhat bizarre experience with the type system today. The second line of this will cause a type error. The problem is the maxdiag (as:bs:cs:ds) bit of the second line:
maxdiag ((a:as):(b:bs):(c:cs):(d:ds):xs) len =
maximum [a*(bs !! 0)*(cs !! 1)*(ds !! 2), maxdiag (as:bs:cs:ds) (len-1)]
It fails with the following error:
Occurs check: cannot construct the infinite type: a0 = [a0]
Expected type: [[a0]]
Actual type: [a0]
In the second argument of `(:)', namely `ds'
In the second argument of `(:)', namely `cs : ds'
When I change the offending part of the second line to maxdiag (as:bs:cs:ds:xs), so that it reads
maxdiag ((a:as):(b:bs):(c:cs):(d:ds):xs) len =
maximum [a*(bs !! 0)*(cs !! 1)*(ds !! 2), maxdiag (as:bs:cs:ds:xs) (len-1)]
... then there is no error. Similarly, if I replace it with maxdiag (as:bs:cs:(ds:xs)) it succeeds. My questions are
What does this error mean?
Why has it occurred?
Why do these two seemingly different things fix it?
The thing to remember is that (:) has the type a -> [a] -> [a], so its first argument is an element, while the second argument is a list with that element type. If the elements are themselves lists, this becomes [a] -> [[a]] -> [[a]].
In your example, as, bs, cs and ds all have type [a], while xs has type [[a]], so cs:ds is an error while ds:xs is well-typed.
The reason for that particular error message is that when you try to use (:) on two things of the same type b, the only way that would work is if b was the same type as [b], but that would be an infinite type which is not allowed.
For the other question, the (:) operator is right-associative, so as:bs:cs:ds:xs is the same as as:(bs:(cs:(ds:xs))) and also as:bs:cs:(ds:xs).
The error:
A.hs:2:63:
Occurs check: cannot construct the infinite type: a0 = [a0]
Expected type: [[a0]]
Actual type: [a0]
In the second argument of `(:)', namely `ds'
In the second argument of `(:)', namely `cs : ds'
means you have recursive constraints on the type, which is illegal. I.e. your type a has to be both a and [a].
The "occurs check" is the technical name for the part of the type checking algorithm that is executing at this point. The "occurs check" prevents the construction of infinitely recursive types.
In my experience failing the occurs check with list-like errors means you're mixing up (:) and (++). That is you're sometimes using a value as a list element, and sometimes as a list itself.
In this case, it is the use of (:) in the expression as:bs:cs:ds.
Probably you mean something like:
[as,bs,cs,ds]++xs
Note that your code is pretty complicated - it makes lots of assumptions about the number and shape of the elements in the list that are very unlikely to be true at all times. I'd be very scared of this code. It would be much safer to:
use pattern matching to rule out the other cases (e.g. empty lists, missing elements)
replace the indexing (!!) with pattern matching.
and think hard about how you can simplify your algorithm.

Resources