2009-04-08 11 views
1

also noch eine andere diskriminiert Union Frage :-)Einstellen Wert eines diskriminiert Union Objekt

Angenommen, ich habe eine diskriminiert Union wie folgt: -

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

Ich möchte in der Lage sein, ein zu verwenden, Funktion appendStringToFoo, wie folgt: -

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

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

Wo hiya ("hiya") und Jojo = D ("Jojo") =.

Natürlich, ich würde auch separate Funktionen appendIntToFoo schreiben weiter, appendCharToFoo usw.

So effektiv, eine ähnliche Funktion wie: -

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

Welche nicht möglich erscheint.

ich nicht wollen, dass Sie Folgendes tun, wenn ich es vermeiden kann: -

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

Da dies bedeutet, dass ich jedes Mal, diesen Code Ich habe eine neue Gewerkschaft Fall neu schreiben müsste.

Irgendwelche Ideen?

+0

Welches Verhalten möchten Sie für appendStringToFoo "x" (B (42))? Insgesamt riecht das nach mir, was versuchst du wirklich (was sind Foo/A/B)? – Brian

+0

Im Allgemeinen müssen Sie jedes Mal, wenn Sie einen neuen Union-Case hinzufügen, den gesamten Code in der Welt, der diesen Union-Typ verwendet, neu schreiben. Dies ist ein Kompromiss zwischen der Verwendung diskriminierter Gewerkschaften und der Verwendung von Klassenhierarchien. – Brian

+0

Dies ist Teil eines Lexers; Ich konstruiere eine Zeichenfolge aus Zeichen, die in einer diskriminierten Gewerkschaftsdarstellung eines Tokens platziert wird. – ljs

Antwort

2

Sie müssen das tun, was Sie nicht tun wollen.

Eine Alternative entlang der Linien von

  • abstrakte Klasse Foo
  • abstrakte Klasse StringyFoo wäre: Foo {void AppendString (string); Zeichenkette S; }
  • Klasse A: StringyFoo
  • Klasse D: StringyFoo
  • abstrakte Klasse IntyFoo: Foo
  • Klasse B: IntyFoo

die potenziell ‚appendString bis zur Festsetzung vermeidet() jedes Mal, wenn Sie fügen Sie ein neuer Tokentyp ", aber ich denke, dass für einen Lexer (wo Foo = Token) Sie insgesamt glücklicher mit dem DU sein werden.

Im Allgemeinen mit Lexing/Parsing, ob Sie Klassenhierarchien und das Besuchermuster verwenden, oder Sie algebraische Datentypen verwenden, müssen Sie immer N * M-Code für N-Features und M-Subtypes schreiben; Es gibt kein Ausweichmanöver, also versuche nicht, süße Tricks zu finden, um es zu vermeiden, es führt nur zu Elend.

+0

Klare Ratschläge. Ich denke, ich werde eine Menge von diesem Zeug auf die harte Tour lernen ...! – ljs

Verwandte Themen