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:-
我希望能够使用一个函数appendStringToFoo,如下所示: -
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").
hiya = A(“hiya”)和yoyo = D(“yoyo”)。
Obviously, I'd also go on to write separate functions appendIntToFoo, appendCharToFoo, etc.
显然,我还会继续编写单独的函数appendIntToFoo,appendCharToFoo等。
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?
1 个解决方案
#1
You have to do the thing you don't want to do.
你必须做你不想做的事情。
An alternative would be along the lines of
另一种选择是沿着这条线
- abstract class Foo
- abstract class StringyFoo : Foo { void AppendString(string); string S; }
- class A : StringyFoo
- class D : StringyFoo
- abstract class IntyFoo : Foo
- class B : IntyFoo
抽象类Foo
abstract class StringyFoo:Foo {void AppendString(string);串S; }
A类:StringyFoo
D类:StringyFoo
抽象类IntyFoo:Foo
B级:IntyFoo
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.
这可能会避免每次添加新的令牌类型时“修复appendString()”,但我认为对于词法分析器(其中Foo = Token),你会对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.
通常使用lexing / parsing,无论是使用类层次结构还是访问者模式,还是使用代数数据类型,您总是必须为N个特征和M个子类型编写N * M代码;没有避免它,所以不要试图找到可爱的技巧来试图避免它,它只会导致痛苦。
#1
You have to do the thing you don't want to do.
你必须做你不想做的事情。
An alternative would be along the lines of
另一种选择是沿着这条线
- abstract class Foo
- abstract class StringyFoo : Foo { void AppendString(string); string S; }
- class A : StringyFoo
- class D : StringyFoo
- abstract class IntyFoo : Foo
- class B : IntyFoo
抽象类Foo
abstract class StringyFoo:Foo {void AppendString(string);串S; }
A类:StringyFoo
D类:StringyFoo
抽象类IntyFoo:Foo
B级:IntyFoo
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.
这可能会避免每次添加新的令牌类型时“修复appendString()”,但我认为对于词法分析器(其中Foo = Token),你会对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.
通常使用lexing / parsing,无论是使用类层次结构还是访问者模式,还是使用代数数据类型,您总是必须为N个特征和M个子类型编写N * M代码;没有避免它,所以不要试图找到可爱的技巧来试图避免它,它只会导致痛苦。