1

Using library functions, define a function halve :: [a ] → ([a ], [a ]) that splits an even-lengthed list into two halves. For example:

> halve [1, 2, 3, 4, 5, 6]
([1, 2, 3], [4, 5, 6])

so far what I have is

halve :: [a] -> ([a],[a])
halve = (\xs -> case xs of
        [] -> ([],[])
        xs -> take ((length xs) `div` 2 ) xs)

and it's wrong since xs -> take ((length x) div 2 ) xs only shows the first half of the list...please help me continue so that it will show the second half of the list.

Ingvaru
  • 53
  • 1
  • 11
  • 1
    http://hackage.haskell.org/package/base-4.8.1.0/docs/Prelude.html#v:splitAt – interjay Nov 12 '15 at 15:59
  • It's getting the first half correctly with `take`, but maybe you need its counterpart `drop`. – Mephy Nov 12 '15 at 16:02
  • Related: http://stackoverflow.com/questions/27090347/haskell-novice-trouble-with-splitting-a-list-in-half – jub0bs Nov 12 '15 at 16:26
  • http://stackoverflow.com/a/32187161/1477667 is probably the best way. – dfeuer Nov 12 '15 at 19:01
  • 1
    It's worth checking whether `halve` is what you need. It might be. Then again, maybe splitting one big list into two small lists half the size would do. Would splitting `[1,2,3,4,5,6]` as the pair `([1,3,5],[2,4,6])` also work for your use case? – pigworker Nov 13 '15 at 00:55

3 Answers3

3

I bumped into the same problem at Programming in Haskell from Graham Hutton. My solution was:

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

Once small thing that gave me some trouble was realising that I needed to use div instead of (/) since length :: Foldable t => t a -> Int and (/) :: Fractional a => a -> a -> a

blasrodri
  • 448
  • 5
  • 16
1

thanks for commenting some solutions. I solved it...here it is

first_halve :: [a] -> [a]
first_halve = (\xs -> case xs of
            [] -> []
            xs -> take ((length xs) `div` 2 ) xs)

second_halve :: [a] -> [a]
second_halve = (\xs -> case xs of
            [] -> []
            xs -> drop ((length xs) `div` 2 ) xs)

halve :: [a] -> ([a],[a])
halve = (\xs -> case xs of
            [] -> ([],[])
            xs -> (first_halve xs, second_halve xs))
Ingvaru
  • 53
  • 1
  • 11
  • 1
    Using [`splitAt`](http://hackage.haskell.org/package/base-4.8.1.0/docs/Prelude.html#v:splitAt) would be more efficient than calling `take` and `drop` separately and computing the length of the list twice. Depending on your requirements, you may not even need to compute the length of the list at all. – jub0bs Nov 12 '15 at 16:20
  • Besides the good suggestion to use `splitAt`, I also suggest considering your case statements carefully. What concern is explicitly checking for `[]` addressing? What do you predict will go wrong if you do not check? (And then, of course, the good-science follow-up question is, _does_ it go wrong in that way?) – Daniel Wagner Nov 12 '15 at 18:40
1

Hm... five years later and I'm probably working through the same text:
Programming in Haskell 1st edition.

Your question gave me the hint I needed to solve the problem:

halve :: [a] -> ([a], [a])
halve xs = (take l xs, drop l xs) 
           where l = div (length xs) 2 
ZygD
  • 22,092
  • 39
  • 79
  • 102
  • That's not actually a good solution though. ``halve xs = splitAt (length xs`div`2) xs`` is preferrable, or if you're feeling pointfree ``halve = splitAt . (`div`2) =<< length``. BTW, it's _six_ years later. – leftaroundabout Nov 02 '21 at 23:50
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/30243868) – Emi OB Nov 03 '21 at 07:54