Typecheck weirdness with lists of lists - haskell

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.

Related

Create concatenate function in Haskell: [String] -> String

I'm having a lot of trouble getting this function to work:
concatenate :: [String] -> String
It is designed to simply take a list of strings and return a single string that is the result of the concatenations of each element of the list from head to tail. I'm trying to stay within the map, foldl, and foldr functions. I feel like I know what the concept of these functions do well enough, but the most common problem I'm running into is that I'm having a conflict of types. GHC will expect a [Char] for example, and I'll put in code that is apparently trying to use a [[Char]] without me knowing it.
For example: concatenate (x:xs) = foldr (++) x (concatenate xs)
And I get the following compile error:
Couldn't match type `Char' with `[Char]'
Expected type: [[Char]]
Actual type: String
In the return type of a call of `concatenate'
In the third argument of `foldr', namely `(concatenate xs)'
In the expression: foldr (++) x (concatenate xs)
I'm very new to Haskell, so please feel free to laugh. Harshness is expected, and welcomed, as long as an explanation fit for a newbie is also included. Thank you for any and all help.
You actually don't need the recursive call there. The function foldr already simulates a recursive call. All you need to do is use:
concatenate :: [String] -> String
concatenate ls = foldr (++) "" ls
And remember that there's a concat function already, which is more generic, as it works on any list of list (as opposed to simply list of strings).

Weird behaviour GHCi Haskell Compiler

In a test I'm asked to infer the type of:
let pr = map head.group.sortBy(flip compare)
I've concluded after inferring it myself that the type was:
Ord a => [a] -> [a]
However when doing :t in GHCi it says the type is:
pr :: [()] -> [()]
What is going on?
Also if in GHCi I do:
map head.group.sortBy(flip compare) [1,2,3,4,100,50,30,25,51,70,61]
I get an error:
Couldn't match expected type `a0 -> [b0]' with actual type `[a1]'
In the return type of a call of `sortBy'
Probable cause: `sortBy' is applied to too many arguments
In the second argument of `(.)', namely
`sortBy (flip compare) [1, 2, 3, 4, ....]'
In the second argument of `(.)', namely
`group . sortBy (flip compare) [1, 2, 3, 4, ....]'
However if I do:
sortBy(flip compare) [1,2,3,4,100,50,30,25,51,70,61]
[100,70,61,51,50,30,25,4,3,2,1]
It works just fine. Why is the first expression failing when the second evaluates sortBy just fine with the exact same arguments?
Your first problem is the dreaded combination of the Monomorphism Restriction, GHCi's inability to see your whole program at once, and GHCi's extended defaulting rules.
In a nutshell, Haskell doesn't like to infer types with polymorphic type class constraints (the Ord a => part of your type signature) for top-level bindings that are written as equations that syntactically do not have arguments. pr = map head.group.sortBy(flip compare) falls foul of this rule (it's a function, so semantically it has arguments, but the equation you're using to define it doesn't), so Haskell wants the Ord-constrained a to be something concrete.
If you put this in a source file and compile it (even via GHCi):
import Data.List
pr = map head.group.sortBy(flip compare)
You get outright errors, like:
foo.hs:3:33:
No instance for (Ord b0) arising from a use of `compare'
The type variable `b0' is ambiguous
Possible cause: the monomorphism restriction applied to the following:
pr :: [b0] -> [b0] (bound at foo.hs:3:1)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
Note: there are several potential instances:
instance Integral a => Ord (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
instance Ord () -- Defined in `GHC.Classes'
instance (Ord a, Ord b) => Ord (a, b) -- Defined in `GHC.Classes'
...plus 22 others
In the first argument of `flip', namely `compare'
In the first argument of `sortBy', namely `(flip compare)'
In the second argument of `(.)', namely `sortBy (flip compare)'
Failed, modules loaded: none.
For some types in particular (notably numeric types) this kind of "ambiguous type variable" error comes up a lot and would be irritating, so Haskell has some defaulting rules. For example, it will assume an ambiguous type variable constrained only by Num should be Integer. Of course, if you use the function anywhere in the same file like so:
import Data.List
pr = map head.group.sortBy(flip compare)
answer = pr [1,2,3,4,100,50,30,25,51,70,61]
then Haskell can take into account. It still refuses to infer a polymorphic type for pr, but in this case pr is only ever used as if it were [Integer] -> [Integer], so it'll give it that type and allow your code to compile, rather than issue the ambiguous type variable error (the Integer itself is also a result of type defaulting).
In GHCi, your code is compiled one statement at a time, so it can't take into account your use of pr to decide what type to give it. It would give you an ambiguous type error except that GHCi has extended defaulting rules, which kick in here to "save the day" and allow your expression to compile. By defaulting the Ord a => a type variable to the unit type (), your declaration can be interpreted as the definition of a function for condensing arbitrary lists of () into [()] (or [] if the input was empty). Thanks GHCi!
You can resolve this in a few of different ways. One is to add an argument to both sides of your definition of pr, like so:
let pr z = map head.group.sortBy(flip compare) $ z
Now the equation defining pr has an argument syntacically (it's type/meaning still has the same number of arguments), the Monomorphism Restriction doesn't kick in, and Haskell is happy to infer a polymorphic type for pr.
Another is to explicitly tell it you don't want to use the Monomorphism Restriction by either adding {-# LANGUAGE NoMonomorphismRestriction #-} to the top of your module, or by using :set -XNomonomorphismRestriction at the GHCi prompt. Then it will again infer the type Ord a => [a] -> [a] for pr.
A third way is to explicitly give the polymorphic type signature for your function:
import Data.List
pr :: Ord a => [a] -> [a]
pr = map head.group.sortBy(flip compare)
Or in GHCi:
> let { pr :: Ord a => [a] -> [a] ; pr = map head.group.sortBy(flip compare) }
Since even with the Monomorphism Restriction in force Haskell is happy for pr to have a polymorphic type, it just won't infer one for it.
The explicit type signature is probably the most common way people avoid this problem in compiled files, because many people consider it good style to always provide type signatures for top level definitions. In GHCi it's pretty annoying, as you can see; I usually turn off the Monomorphism Restriction there.
As for your second problem, I'm afraid this:
map head.group.sortBy(flip compare) [1,2,3,4,100,50,30,25,51,70,61]
is very different from this:
pr [1,2,3,4,100,50,30,25,51,70,61]
When you've got pr defined as a function, pr refers to the whole function map head.group.sortBy(flip compare), so feeding it an argument feeds an argument to that function. But when you write out the whole expression, just sticking a list to the right of it does not pass it as an argument to the whole expression. It's parsed a bit more like this:
(map head) . (group) . (sortBy (flip compare) [1,2,3,4,100,50,30,25,51,70,61])
As you can see, the list is inside the last function in the pipeline; sortBy (flip compare) [1,2,3,4,100,50,30,25,51,70,61] is being used as a function, which will take an argument and feed its output further through the pipeline (to group). That clearly doesn't make sense, and is why you get an error message complaining about too many arguments being given to sortBy; it's not that you have provided too many arguments to sortBy, but rather that you've provided all its arguments and then used it in a position where it would have to be able to take one more.
This can sometimes be surprising until you get used to it, but any alternative is surprising more frequently (you implicitly depended on parsing working this way in your use of map head and sortBy (flip compare)). All you need to do is remember that ordinary function application (by just sticking two expressions next to each other) is always higher precedence than infix operators (like .); whenever you've got an expression mixing infix operators and ordinary application, each normal application chain (groups of non-operator expressions separated only by whitespace) becomes only a single argument as far as the infix operators are concerned (and then precedence/associativity is used to resolve what the arguments of the infix operators are).
To fix it, you need to add parentheses around the composition pipeline before you introduce the argument, like so:
(map head.group.sortBy(flip compare)) [1,2,3,4,100,50,30,25,51,70,61]
Or use $ to put a "wall" between the composition pipeline and the argument, like so:
map head.group.sortBy(flip compare) $ [1,2,3,4,100,50,30,25,51,70,61]
This works because $ is another infix operator, so it forces all the "normal application" sequences to its left and right to be resolved before one can be applied to the other. It's also a very low precedence operator, so it almost always works when there are other infix operators in play as well (like the .). It's quite a common idiom in Haskell to write expressions of the form f . g . h $ a.
You've been bitten by defaulting, where GHCi (interactive GHCi, not GHC compiling something) will put () in any uninstantiated type parameter in certain cases.
I think you've mixed up . and $. Consider your original expression:
map head . group . sortBy(flip compare) [1,2,3,4,100,50,30,25,51,70,61]
That composes the functions map head, group, and sortBy (flip compare) [...]. Unfortunately, sortBy (flip compare) [...] is a list, not a function, so it can't be composed like that. sortBy (flip compare), however, is, and if we compose those functions together and then apply that function to the list, it'll work:
map head . group . sortBy (flip compare) $ [1,2,3,4,100,50,30,25,51,70,61]

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

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.

Haskell filter function on strings

Is there a way to use the filter function on Strings, this way:
filter (=="!") "!!some!!_!!string!!"
should output "some_string" (case above). Right now all i get is a type error:
Couldn't match expected type `[Char]' against inferred type `Char'
If i change the second filter argument type to ["!!some!!_!!string!!"], the type error disappears, yet only an empty list is outputted. (Not exactly what i want)
I thought that strings were lists but obviously "!!some!!_!!string!!" isn't regarded as a list but as a char.
Any hints someone ?
Prelude> filter (/='!') "!!some!!_!!string!!"
"some_string"
The type of filter is (a -> Bool) -> [a] -> [a]. Since the 2nd argument is a String = [Char], meaning [a] = String = [Char], we infer that a must be a Char. The function therefore must take a Char as input. Therefore, you need to use '!', not "!".

New to Haskell, don't understand why I'm getting an infinite type error

module Main where
rev :: [a] -> [a]
rev (x:[]) = x
rev (x:xs) = (rev xs):x
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
main = do
print (rev lst)
I'm working my way through 99 Haskell Problems and trying to write a function to reverse a list (yes, I am aware there's one already in the prelude).
My problem is that when I try to compile the code above (or just type the function definition into GHCi), I get:
Occurs check: cannot construct the infinite type: a = [a]
In the expression: rev :: [a] -> [a]
In the definition of `it': it = rev :: [a] -> [a]
I'm not quite sure where I'm going wrong with my types to get this error. I'm guessing it has something to do with how I'm pattern matching, but I don't know why.
Travis is correct regarding the specific error, but for the sake of anyone who finds this question later when searching for "infinite type errors", here's what that (seemingly cryptic) message means:
A function having type variables in its signature means that it doesn't care what type it receives there--it doesn't inspect the values of that type, they're just black boxes. However, when actually using such a function, the type variables will be nailed down to something more concrete on a per-use basis. Specific types aren't required, though--the type variables can also be filled in with other type variables. This unification process is part of type inference and lets the compiler combine unknown type variables in different parts of the program.
Errors that occur when binding type variables can often seem cryptic at first, particularly when GHC attempts to combine variables in the same type signature. For instance:
If the compiler tries to unify two distinct variables, it will complain about "rigid type variables bound by a type signature", which means that it can't unify the two types because you explicitly told it they were distinct.
If the compiler tries to unify a type variable with a subset of itself, such as deciding that the type variable a should be the same as [a], it will complain about an infinite type, which just means that naive unification says that a is actually [a] is actually [[a]] is actually [[[a]]]... and so on.
The problem is that the type of (:) is a -> [a] -> [a], but your third line (rev (x:xs) = (rev xs):x) would need it to be [a] -> a -> [a].
The function you want is commonly called snoc (i.e. the opposite of cons, which is the name for (:) in the Lisp world). It's not provided for lists in the Haskell standard libraries, but you can easily do the same thing with (++):
rev :: [a] -> [a]
rev (x:[]) = [x]
rev (x:xs) = rev xs ++ [x]
EDIT: There was also a problem in the second line, as Landei points out in the comments: you were returning the element, not a list containing the element.

Resources