thomaseding / mtg-pure

Purely functional Haskell "Magic: The Gathering" card model and game engine.
BSD 3-Clause "New" or "Revised" License
10 stars 0 forks source link

Create programming guide for ObjectN encoding #2

Open thomaseding opened 1 year ago

thomaseding commented 11 months ago

CONCEPTS:


OT (object type):

This is a vanilla enum of (generalized) singular MTG object types.

Examples: OTInstant, OTActivatedAbility, OTCreature


OTKN (object type kind N):

While the type OTKN is not literally in the code, this is a family of OTK0, OTK1, ... OTK12 type aliases for type level [OT] of the corresponding length. By convention the OTs in the lists are sorted alphabetically. This is to ensure unique representations. (Failure to do so is a bug, and if such a type is actually used by the engine, I think it wouldn't compile due to missing class instances or GADT constructors for the non-sorted type list.) The special case for N=0, OTK0 doesn't actually contain object type information in it. This is useful for doing type erasure.

Examples: OTK1 'OTSorcery, OTK1 'OTLand, OTK2 'OTArtifact 'OTCreature


OTN (object type N):

This is a GADT parameterized generically on OTKN and has corresponding constructors for them. This is the composite object type form of OT. Convenience type aliases are provided for each of the concrete OTN otk families: OT0, OT1 a, OT2 a b, etc. The corresponding OTN constructors have the names OT0, OT1, ..., OT12 as well. The constructors are each nullary and just store relevant class instance dictionary information for each of the encoded object types.

Examples: OT1 'OTEnchantment, OT2 'OTCreature 'OTPlayer


ObjectN (object N)

This is a GADT parameterized by OTN types and represents a hierarchical encoding of how to lift a (composite) object of fewer types into one of more types. For example, one might want to lift a "creature" into a "creature and/or planeswalker" representation ("and/or" is used because the encoding doesn't care about how one interprets its structure, but in practice this would mean either "and" xor "or" depending on the specific use case). Furthermore one might want to further lift that into a "permanent" representation (type OTPermanent = OT5 'OTArtifact 'OTCreature 'OTEnchantment 'OTLand 'OTPlaneswalker) and so on.

Lifting is done in one of two fashions through their corresponding constructors: (1) Lifting an object of a singular a :: OT into ObjectN (OT3 a b c) or some permutation of [a, b, c]. This pattern generalizes to other OTKN N-sizes. (2) Lifting a composite object of ObjectN (OT3 a b c) to ObjectN (OT4 a b c d) or whatever the correct alphabetically sorted permutation of a b c d would be. This pattern generalizes to other OTKN N-sizes.


ToObjectN'

While the type class ToObjectN' is not literally in the code, there is a family of ToObject1', ToObject2', ...ToObject12' type classes that promote Object a to ObjectN a b c d so-to-speak. src/MtgPure/Model/Object/ToObjectN/CodeGen.hs is used to generate these instances in a way that enforces the alphabetical OT type level list orderings


ToObjectN

Similar to ToObjectN' but lifts "subset" ObjectN into superset ObjectN encodings. So for example lifting a ObjectN a b into an ObjectN a b c or ObjectN a b c d and so forth. src/MtgPure/Model/Object/ToObjectN/CodeGen.hs is used to generate these instances in a way that enforces the alphabetical OT type level list orderings