質問

Is it possible to add constant field values to F# discriminated unions?

Can I do something like this?

type Suit
  | Clubs("C")
  | Diamonds("D")
  | Hearts("H")
  | Spades("S")
  with
    override this.ToString() =
      // print out the letter associated with the specific item
  end

If I were writing a Java enum, I would add a private value to the constructor like so:

public enum Suit {
  CLUBS("C"),
  DIAMONDS("D"),
  HEARTS("H"),
  SPADES("S");

  private final String symbol;

  Suit(final String symbol) {
    this.symbol = symbol;
  }

  @Override
  public String toString() {
    return symbol;
  }
}
役に立ちましたか?

解決

Just for completeness this is what is meant:

type Suit = 
  | Clubs
  | Diamonds
  | Hearts
  | Spades
  with
    override this.ToString() =
        match this with
        | Clubs -> "C"
        | Diamonds -> "D"
        | Hearts -> "H"
        | Spades -> "S"

他のヒント

The closest thing to your requirement is F# enums:

type Suit =
    | Diamonds = 'D'
    | Clubs = 'C'
    | Hearts = 'H'
    | Spades = 'S'

let a = Suit.Spades.ToString("g");;
// val a : string = "Spades"

let b = Suit.Spades.ToString("d");; 
// val b : string = "S"

The problem with F# enums is non-exhaustive pattern matching. You have to use wildcard (_) as the last pattern when manipulating enums. Therefore, people tend to prefer discriminated unions and write explicit ToString function.

Another solution is to make a mapping between constructors and corresponding string values. This is helpful in case we need to add more constructors:

type SuitFactory() =
    static member Names = dict [ Clubs, "C"; 
                                 Diamonds, "D";
                                 Hearts, "H";
                                 Spades, "S" ]
and Suit = 
  | Clubs
  | Diamonds
  | Hearts
  | Spades
  with override x.ToString() = SuitFactory.Names.[x]

Pretty sure you can't, but is trivial to write a function that pattern matches and then compose the two things

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top