Using a variant as a key in a hashmap

I would like to use a variant as a key in my HashMap, for example

let Country = { 
  #germany;
  #france; 
  #england;
  ...
}

func countryEqual(c1: Country, c2: Country): bool { c1 == c2 };

let countryMap: HashMap<Country, Text> = HashMap<Country, Text>(
  countries.size(),
  countryEqual,
  //what could/should I use here as a hash?
);

I have a few questions based off of this example:

  1. Is this possible/recomended usage of a variant, or should I be using a type union of country strings, or even a record and just not have my HashMap key be typed?
  2. If this is possible, is my variant equals function valid in Motoko or would I need a toText() function? I’m assuming this works based on how a variant is used in pattern matching, but don’t understand the underlying representation of a variant.
  3. As mentioned in the comment above, is a variant hashable as is or would I need to toText() it first and hash the Text?

I think it’s a reasonable use case. I try to avoid strings when I can use something more strongly typed.

If it type checks then I assume it is valid :slightly_smiling_face:

I don’t think there’s anything provided for you. My understanding is that you’d need to provide a hashing function.

The constructor for HashMap takes a keyHash : K -> Hash.Hash function, so you’d need to implement that.

I suppose technically something like this would work but you’d probably want to use a popular hashing algorithm on the tag name as text, or something like that.

hashCountry(country : Country) : Hash.Hash {
  Hash.hash(
    switch {
      case #england 0;
      case #france 1;
      case #germany 2;
    }
  )
};
1 Like

If this is possible, is my variant equals function valid in Motoko

I’m no OCaml expert, but I think it should work.

1 Like