1

I am new to haskell and trying out some exercises

I dont understand whats the error generated and why it is generated

split = foldr 
        (\x y -> y:x)
        [[]]

the error on the interpretator is as below

    Occurs check: cannot construct the infinite type: a0 = [a0]
    In the first argument of `(:)', namely `y'
    In the expression: y : x
    In the first argument of `foldr', namely `(\ x y -> y : x)'
Failed, modules loaded: none.

anyone can help? Thanks in advance

2
  • 1
    Can you give us more details about he expected type of split? Because just reversing y with x does nothing, it gives you back the same list of list that was given as input, it is the same as foldr (:) [[]] . Commented Oct 10, 2012 at 15:45
  • like maybe for example splitting into even and odd numbers? Commented Oct 10, 2012 at 15:49

3 Answers 3

6

Type of foldr is

foldr :: (a -> b -> b) -> b -> [a] -> b

so in split

split = foldr (\x y -> y:x) [[]]

y and y:x has to be of same type, which is not possible for any x and y as y:x will always be one step deeper in the list than y.

I think you wanted to do x:y?

Sign up to request clarification or add additional context in comments.

Comments

2

Recall the type of foldr: (a -> b -> b) -> b -> [a] -> b. This says that foldr expects a function that combines an element of the list with a value of the final result type, producing a new value of the result type.

For the first argument, you've given foldr the function \x y -> y:x, where x will be the list elements and y the result of the next step to the right; and the result of applying this lambda should have the same type as y.

But the type of (:) is a -> [a] -> [a]--that is, it appends a single element to the head of a list. In the expression y:x, you're taking something of the "result" type and using it as an element of a list used as the result.

Because of that, GHC attempts to infer that the result type b is the same as the type [b], which is then of course the same as the type [[b]], and [[[b]]]... and so on. Thus it complains about an "infinite type".

4 Comments

can u explain the last part?I dont quite catch. what does the '[[]]' refer to?
@edelweiss: Just like [b] is a list with elements of type b, [[b]] is a list with elements of type [b]. In other words, a list of lists. Likewise, [[[b]]] is a list of lists of lists, &c.
am i correct to say that '[[]]' refers to the type of output expected?
how do I actually achieve this type of outing in haskell?
1

The posts before me answer your question, but after your comment i can see that you want a function that splits your list by a predicate.

You can use groupWith::Ord b => (a -> b) -> [a] -> [[a]] from the module GHC.Exts and supply it with a function of type (a -> Bool) in your example:

groupWith even [1,2,3,4,5,6] yields [[1,3,5],[2,4,6]]

Also, something ugly but that achieves the type of "outing" you want is:

split::Eq a => (a -> Bool) -> [a] -> [[a]]
split f ls = (ls \\ rl):rl:[]
    where rl = filter f ls

But this will always split the supplied list in just two lists because of the binary function you supply.

2 Comments

Data.List.partition may be more appropriate here.
That should be the way to go, and that would be also something that he could easily implement, but he was also interested that the output type be a list of lists and not a tuple.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.