Consider the following data definition:
data Foo = A{field::Int}
| B{field::Int}
| C
| D
Now let's say we want to write a function that takes a Foo and increases field if it exists, and leave it unchanged otherwise:
incFoo :: Foo -> Foo
incFoo A{field=n} = A{field=n+1}
incFoo B{field=n} = B{field=n+1}
incFoo x = x
This naive approach leads to some code duplication. But the fact that both A and B shares field allows us to rewrite it:
incFoo :: Foo -> Foo
incFoo x | hasField x, n <- field x = x{field=n+1}
incFoo x = x
hasField A{} = True
hasField B{} = True
hasField _ = False
Less elegant, but that's defiantly easier to maintain when the actual manipulation is complex. The key feature here is x{field=n+1} - record syntax allows us to "update" field without specifying x's type. Considering this, I'd expect something similar to the following syntax (which is not supported):
incFoo :: Foo -> Foo
incFoo x{field=n} = x{field=n+1}
incFoo x = x
I've considered using View Patterns, but since field is a partial function (field C raises an error) it'll require wrapping it in more boilerplate code.
So my question is: why there's no support for the above syntax, and is there any elegant way of implementing a similar behavior?
Thanks!