Haskell: Split a list using list comprehension

4.7k views Asked by At

How do you split a list into halves using list comprehension?

e.g. If I have [1,1,2,2,3,3,4,4,5,5] and I only want [1,1,2,2,3]

my attempts so far:

half mylist = [r | mylist!r ; r <- [0..(#mylist div 2)] ]    ||does not work

Any thoughts?

[Nb: This isn't actually Haskell but similar. ! is used for indexing list, and # gives length)

Edit::

Okay so it turns out that

half mylist = [r | r <- [mylist!0..mylist!(#mylist div 2)] ]

works, but only in list of numbers and not strings. Any clues?

2

There are 2 answers

4
Don Stewart On BEST ANSWER

This isn't really an appropriate thing to do with a list comprehension. List comprehensions are alternate syntax for maps and filters (and zips). Splitting a list is a fold.

As such, you should consider a different approach. E.g.

halve :: [a] -> [a]
halve [] = []
halve xs = take (n `div` 2) xs
    where n = length xs

Splitting isn't a great operation on large lists, since you take the length first (so it is always n + n/2 operations on the list. It is more appropriate for array-like types that have O(1) length and split.

1
Chris Rice On

Another possible solution, using a boolean guard:

half xs = [x | (x,i) <- zip xs [1..], let m = length xs `div` 2, i <= m]

But as Don Stewart says, a list comprehension is not really the right tool for this job.