[Haskell-beginners] List Manipulation

Daniel Fischer daniel.is.fischer at web.de
Thu Sep 9 14:46:05 EDT 2010


On Thursday 09 September 2010 19:12:21, Lorenzo Isella wrote:
>
> Up to some extent, I am done (later on I found out that reading this
> into a matrix for hmatrix is a one-liner), but I would like to achieve
> more just performing standard list manipulations.
> For instance, since my data files are always this simple (integers/real
> arrays of numbers)
>
> (1) How can I tell the length of every sublist in my list?

map length

gives the list of lengths

(if all sublists are known to have the same length, of course one length is 
enough, e.g. head . map length if there is known to be at least one 
sublist).

> (2) How can I e.g. stitch together the 1st element in every sublist in
> order to get the 1st column of the original data file?

map head does this. More general,

import Data.List

and then

transpose

does what you'd expect, so

firstColumn xss = head (transpose xss)

can do it.

But there's a catch.
As a rule, don't use head.

head is a partial function, if it's called with an empty list, it throws an 
error. And that error isn't particularly informative. So if you have 
multiple calls to head in your programme and one of them throws an error, 
it can be a major pain to find out what went wrong (and sometimes an empty 
list where a nonempty one is expected isn't an unrecoverable error, in 
those cases using head is wrong in an additional way).
It's okay to use head in places where it is known that it can't be called 
on an empty list because its argument comes from a function that produces 
only nonempty lists (some people disagree with that opinion and think head 
should never be called, on principle or because of a feared slippery 
slope).
But in general, don't use head.

So, how do we do it without head?

For example,

-- default value if there is no sublist
sublistLength [] = 0
sublistLength (xs : _) = length xs

Or use Maybe to indicate whether it's a real result or not,

sublistLength [] = Nothing
sublistLength (xs : _) = Just (length xs)

{-
import Data.Maybe

sublistLength = fmap length . listToMaybe
-}

-- skip empty sublists
firstColumn xss = [x | (x : _) <- xss]

-- indicate empty sublists with Maybe
import Data.Maybe -- for listToMaybe
firstColumn xss = map listToMaybe xss

That loses a little conciseness, but it buys you safety.

>
> Many thanks
>
> Lorenzo


More information about the Beginners mailing list