libminizinc
libminizinc copied to clipboard
Feature idea: Product enum construction
Currently it is possible to construct new enums using constructors with a single argument, making a simple mapping into the new enum type.
It could sometimes be interesting to be able to use multiple arguments to create products of base enums. Consider the following hypothetical way in which one could use such a feature to model playing cards
enum Suits = {Hearts, Diamonds, Spades, Clubs};
enum Honours = {Ace, Jack, Queen, King};
enum Values = V(2..10);
enum Ranks = Ace({Ace}) ++ Value(Values) ++ Court({Jack, Queen, King});
enum Cards = Card(Suits, Ranks);
The idea here would be that Card
takes a suit and a rank and produces a card value.
An additional use-case for this could be as a simple way to map between 2D and 1D coordinates. Consider the following fragment
set of int: Dom;;
int: n = 12;
set of int: N = 1..n;
int: m = 14;
set of int: M = 1..m;
array[N, M] of var Dom: board;
enum Pos = P(N, M);
array[Pos] of var Dom: board1d = array1d(board);
The inverse constructor for Pos
(P^-1
) could give back a tuple of values, so that indexing from a pos value could be done using code like the following fragment:
Pos: pos;
board[P^-1(pos)[1], P^-1(pos)[2]]
This becomes a bit clunky (the suffix ^-1
is ergonomically bad and not the most readable, but I have no other suggestion at this moment), but can be hidden using some simple function definitions. The result of the inverse needs to be a tuple, since the domains could be completely different types. I know that MiniZinc does not have tuples (yet?), but this could be a magically blessed type construction that is for now unnameable in the type system.