My question is related to a more general question on Haskell program design. But I would like to focus on a specific use case.
I defined a data type (e.g. Foo), and used it in a function (e.g. f) through pattern matching. Later, I realized that the type (Foo) requires some additional field to support new functionalities. However, adding the field would change how the type can be used; i.e. the existing functions depending on the type could be affected. Adding new functionalities to existing code, however unappealing, is hard to avoid. I am wondering what are the best practices at the Haskell language level to minimize the impact of such kind of modifications.
For example, the existing code is:
data Foo = Foo {
vv :: [Int]
}
f :: Foo -> Int
f (Foo v) = sum v
The function f will be syntax wrong if I add another field to Foo:
data Foo = Foo {
vv :: [Int]
uu :: [Int]
}
However, if I had defined function f as the following in the first place:
f :: Foo -> Int
f foo = sum $ vv foo
, then even with the modification on Foo, f would still be correct.