Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple haskell splitlist

Tags:

haskell

I have the following function which takes a list and returns two sublists split at a given element n. However, I only need to split it in half, with odd length lists having a larger first sublist

splitlist :: [a] -> Int -> ([a],[a])
splitlist [] = ([],[])
splitlist l@(x : xs) n | n > 0     = (x : ys, zs)
               | otherwise = (l, [])
    where (ys,zs) = splitlist xs (n - 1)

I know I need to change the signature to [a] -> ([a],[a]), but where in the code should I put something like length(xs) so that I don't break recursion?

like image 471
kqualters Avatar asked Dec 09 '12 04:12

kqualters


2 Answers

In a real program you should probably use

splitlist :: [a] -> ([a], [a])
splitlist xs = splitAt ((length xs + 1) `div` 2) xs

(i.e. something along the lines of dreamcrash's answer.)

But if, for learning purposes, you're looking for an explicitly recursive solution, study this:

splitlist :: [a] -> ([a], [a])
splitlist xs = f xs xs where
    f (y : ys) (_ : _ : zs) =
        let (as, bs) = f ys zs
        in (y : as, bs)
    f (y : ys) (_ : []) = (y : [], ys)
    f ys [] = ([], ys)
like image 120
dave4420 Avatar answered Oct 15 '22 16:10

dave4420


You can do it using take and drop:

splitlist :: [a] -> ([a],[a])
splitlist [] = ([],[])
splitlist l  = let half = (length(l) +1)`div` 2
               in (take half l, drop half l)

or you can take advantage of the function splitAt:

splitlist list = splitAt ((length (list) + 1) `div` 2) list
like image 29
dreamcrash Avatar answered Oct 15 '22 18:10

dreamcrash