[Haskell-cafe] Is there a nicer way to do this?

Don Stewart dons at galois.com
Sun Jul 6 20:42:04 EDT 2008


mfeathers:
> Don Stewart wrote:
> >mfeathers:
> >>
> >>segment :: Int -> [a] -> [[a]]
> >>segment 0 _ = []
> >>segment _ [] = []
> >>segment n x = (take n x) : segment n (drop n x)
> >
> >The first set of parens can go,
> >
> >  segment n x = take n x : segment n (drop n x)
> >
> >>I did a version of this which used splitAt but I wasn't sure whether it 
> >>was going to buy me anything re performance that would justify its 
> >>ugliness.
> >
> >Besides,
> >
> >  splitAt n xs =  (take n xs, drop n xs)
> 
> Thanks.  That is odd, though.  It makes me wonder what to expect re 
> optimization.  Would the compiler/runtime know that splitAt could be 
> done in a single pass?

Not with that definition. It would require some moderately unusual fusion
combining the take and drop into a single fold with the (,) on the inside,
rather than on the outside.

However, GHC actually implements splitAt as:

    splitAt (I n) ls
      | n < 0       = ([], ls)
      | otherwise   = splitAt' n ls
        where
            splitAt' :: Int -> [a] -> ([a], [a])
            splitAt' 0 xs     = ([], xs)
            splitAt' _  xs@[] = (xs, xs)
            splitAt' m (x:xs) = (x:xs', xs'')
              where
                (xs', xs'') = splitAt' (m - 1) xs

So there may be some benefit.

-- Don



More information about the Haskell-Cafe mailing list