"Group" Theory

Last time around we saw the function "intercalate". This could take a list of lists, and produces a single list, separated by the list from the first argument. But today, we'll take a look at a couple functions that work in reverse. The "group" functions take something like a flat, single-level list, and turn it into a list of lists.

group :: (Eq a) => [a] -> [[a]]

groupBy :: (a -> a -> Bool) -> [a] -> [[a]]

When you use the basic group function, you'll take your list and turn it into a list of lists where each list contains successive elements that are equal.

>> group [1, 2, 2, 3, 4, 4, 4]
[[1], [2, 2], [3], [4, 4, 4]]

This is useful for answering a question like "What is the longest consecutive sequence in my list?" Like any list function, it can be used on strings.

>> group "Hello Jimmy"
["H", "e", "ll", "o", " ", "J", "i", "mm", "y"]

The groupBy function provides more utility. It lets you pass in your own comparison test. For example, here's a rudimentary way to separate a raw CSV string. You "group" all characters that aren't strings, and then filter out the commas.

separateCSV :: String -> [String]
separateCSV s = filter (/= ",") (groupBy (\c1 c2 -> c1 /= ',' && c2 /= ',') s)

...

>> separateCSV "Hello,there,my,friend"
["Hello", "there", "my", "friend"]

Here's another example. Suppose you have an array representing a two-dimensional matrix:

myArray :: Array (Int, Int) Double

The assocs function of the Array library will give you a flat list. But you can make this into a list of lists, where each list is a row:

myArray :: Array (Int, Int) Double)

rows = groupBy (\((a, _), _) ((b, _), _) -> a == b) (assocs myArray)

This is a common pattern you can observe in list functions. There's often a "basic" version of a function, and then a version ending in By that you can augment with a predicate or comparison function so you can use it on more complicated data.

If you enjoyed this article, sign up for our mailing list to our newsletter so that you get access to all our subscriber resources. One example is our Beginners Checklist! This is a useful resource if you're still taking your first steps with Haskell!

Previous
Previous

Transposing Rows

Next
Next

In the Middle: Intersperse and Intercalate