调整区分联合对象的值

时间:2009-04-08 22:23:38

标签: f#

所以,又一个受歧视的工会问题: - )

假设我有一个像这样的歧视联盟: -

type Foo =
  | A of string
  | B of int
  | C of char
  | D of string

我希望能够使用一个函数appendStringToFoo,如下所示: -

let someVal = A("hi")
let anotherVal = D("yo")

let hiya = someVal |> appendStringToFoo "ya"
let yoyo = anotherVal |> appendStringToFoo "yo"

hiya = A(“hiya”) 和yoyo = D(“yoyo”)。

显然,我还会继续编写单独的函数appendIntToFoo,appendCharToFoo等。

因此,有效地,类似于以下函数: -

let appendStringToFoo str fooValue =
  fooValue(fooValue.Value + str)

这似乎不可能。

如果可以避免,我 想要做以下事情: -

let appendStringToFoo str fooValue =
    match fooValue with
    | A(originalStr) -> A(originalStr + str)
    | D(originalStr) -> D(originalStr + str)

因为这意味着每次添加新的联合案例时我都必须重新编写此代码。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

你必须做你不想做的事情。

另一种选择是

  • 抽象类Foo
  • abstract class StringyFoo:Foo {void AppendString(string);字符串S; }
  • A类:StringyFoo
  • D类:StringyFoo
  • 抽象类IntyFoo:Foo
  • B级:IntyFoo

这可能会避免每次添加新的令牌类型时“修复appendString()”,但我认为对于词法分析器(其中Foo = Token),你会对DU更加满意。

通常使用lexing / parsing,无论是使用类层次结构还是访问者模式,还是使用代数数据类型,都必须为N个特征和M个子类型编写N * M代码;没有避免它,所以不要试图找到可爱的技巧来试图避免它,它只会导致痛苦。