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.

2 comments:

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.