Reputation: 37817
So, yet another discriminated union question :-)
Assume I have a discriminated union like so:-
type Foo =
| A of string
| B of int
| C of char
| D of string
I would like to be able to use a function, appendStringToFoo, as follows:-
let someVal = A("hi")
let anotherVal = D("yo")
let hiya = someVal |> appendStringToFoo "ya"
let yoyo = anotherVal |> appendStringToFoo "yo"
Where hiya = A("hiya") and yoyo = D("yoyo").
Obviously, I'd also go on to write separate functions appendIntToFoo, appendCharToFoo, etc.
So, effectively, a function similar to:-
let appendStringToFoo str fooValue =
fooValue(fooValue.Value + str)
Which doesn't seem possible.
I do not want to do the following if I can avoid it:-
let appendStringToFoo str fooValue =
match fooValue with
| A(originalStr) -> A(originalStr + str)
| D(originalStr) -> D(originalStr + str)
As that means I'd have to re-write this code every time I added a new union case.
Any ideas?
Upvotes: 1
Views: 274
Reputation: 118895
You have to do the thing you don't want to do.
An alternative would be along the lines of
which potentially avoids 'fixing up appendString() each time you add a new token type', but I think that for a lexer (where Foo=Token) you'll be happier overall with the DU.
In general with lexing/parsing, whether you use class hierarchies and the Visitor pattern, or you use algebraic data types, you always must write N*M code for N features and M subtypes; there's no avoiding it, so don't bother trying to find cute tricks to try to avoid it, it only leads to misery.
Upvotes: 2