I am working on a function in Haskell that will take one list and divide it into two evenly sized lists. Here is what I have:
split (x:y:xs) = split2 ([((length(x:y:xs) `div` 2)-2) : x ++ y] : [xs])
split2 (x:xs:[y:ys]) = split2 ((x-1) : [xs] ++ y : [ys])
split2 (0:xs:[y:ys]) = (xs:[y:ys])
The function takes the first two elements of a list, and puts them together into list #2 and appends the first list as a second element. It then gets the length of the list, and divides it by two to find out how many times to run taking into account the fact that it already removed two elements from the first list. It then takes those two pieces of information and puts it into split2, which takes another element from the first list and appends it to the second list in the first element, also it counts down 1 from the number of runs and then runs again.
Problem is, when I run it I get this:
Functions.hs:19:49:
Occurs check: cannot construct the infinite type: t0 = [t0]
In the first argument of `(:)', namely `(y)'
19 refers to line 2, the first split2 function. Not exactly sure how to go about fixing this error. Any ideas?
It’s hard to know where to start…
Let’s define functions from ever larger chunks of the expression in
split2.Ok, so the argument is a list of something, and it returns an
IntHere, the
lengthIntis being cons’d withx, soxmust be[Int], so(x:y:xs)must be[[Int]]. We can also infer thatyhas the same type asx, andxsis a list of things of the same type;[[Int]]. So thex ++ ywill also be[Int].So,
[xs]will have type[[[Int]]]. Now, we wrap the result in a list constructor, and cons it with[xs]:I’m guessing you didn’t expect the argument to be a list of lists of lists of
Ints.Now, if we look at
split2, the argument pattern(x:xs:[y:ys])implies that it is of type:The rhs of the first definition of
split2tries to construct a new list by concatenating(x-1) : [xs]andy : [ys]. However, if we substitute the types into they : [ys], we find:But since
(:) :: a -> [a] -> [a], this means that[[a]]must be the same type as[a], oramust be a list of itself, which is not possible.The
(x-1)is also badly typed, because it attempts to subtract one from a list.I can’t tell if you want to split the lists into even and odd elements, or into first and second halves.
Here are two versions that split into the first and second halves, rounding down (RD) or up (RU) if the length is odd:
Here’s a version that splits the list into even and odd elements: