Friday, June 27, 2008

Pattern Matching can be Fragile

Pattern matching in Haskell is so useful, that I have found myself using it extensively. However, in certain cases it has lead to code that doesn't adapt to change particularly well. Consider the following:

data Foo = Bar String Int Int

f (Bar _ x y) = x + y

In this case, pattern matching has provided a very convenient way for the function f to bind names (x and y) to the instances of the two Int elements in the Bar constructor.

The key point though, is that f has encoded the entire structure of the Bar constuctor even though it only operates on a portion of it - the two Int elements.

This means that should the structure of Bar change by removing the String or by adding other elements, the definition of f will need to change, even though the actual computation it performs is unaffected. More generally, if the number of elements in a Data Constructor is changed, all functions that pattern match on that constructor will need to be modified, whether their body is concerned with those elements or not.


Nick said...

Hmm, interesting point. I can't help but feel I'm being teased here though - what's the solution? How do you re-write it so that it's easier to maintain? This might be obvious to some, but I've only started re-learning haskell recently :)

Smarter data accessors: Foo -> (Int,Int) and function composition?

Brad Clow said...

Nick, I don't have a comprehensive resolution at this stage, so my intention was simply to state the problem clearly so I could stop thinking about it for the moment. :-)

Accessor functions are one alternative (and I will try and write my thoughts on that soon), but I think there is more to it - which requires more thought and investigation.