
Phabstractic: Tagged Union Data Type
asherwunk/phabstractic now has support for a tagged union data type.
Tagged Union
Tagged unions are also called sum type, disjoint union, discriminated union, and variant (record). A tagged union here is a value that can only hold specific types of values, but may be any one of these types of values can be stored at any one time. Only one of the types can be in use at any one time, and an object property explicitly indicates which one is in use. This creates a form of “data structure polymorphism” where a value is of a specific type, rather than an “is_a” relationship. Tagged unions are most important in functional languages such as ML and Haskell. For more information on this somewhat obscure data type please see the Wikipedia article.
Implementation
Using the Restrictions Predicate Data Type (github) we can easily set up a tagged union class. A tagged union must identify its type, its value, and its type restrictions. In previous versions, the type restrictions are set on the construction of a tagged union data structure, but in the most recent version you can modify the restrictions of a tagged union dynamically using Phabstractic\Data\Types\TaggedUnion::setRestrictions() . The code for these looks like:
namespace Falcraft\Data\Types { class TaggedUnion { private $type = null; private $restrictions = null; private $value = null; } }
Dynamic Restrictions
In the new version, as noted above, you can set new restrictions at run time. These are simply a modification or replacement of the restrictions property:
public function getRestrictions() { return $this->restrictions; } public function setRestrictions(TypesResource\FilterInterface $restrictions) { $this->restrictions = $restrictions; }
Checking Value Types
The heart of the tagged union lies in the setting of the value. When the value is set it must comply with the restrictions placed on the tagged union at construction. The code for that looks like:
public function set( $value ) { // Get the values type as a Phabstractic\Data\Types\Type object. // getValueType returns false on failure, which is possible // since it normally returns an object of Falcraft\Data\Types\Type // I can't think of a value that is untypeable at this moment. if (($typeEnum = Type\getValueType($value)) === false) { throw new TypesException\RuntimeException( 'Phabstractic\Data\Types\TaggedUnion->set: Untypeable Value'); } if ($this->restrictions->isAllowed($typeEnum) == false) { throw new TypesException\InvalidArgumentException( 'Phabstractic\Data\Types\TaggedUnion->set: Illegal Value'); } $this->type = $typeEnum; $this->value = $value; }
We use the typing functions (github) provided by the Phabstractic Data Types library to obtain the type of the piece of data coming in. All values should be typeable, so it is rare to incur a type error (you must really be doing something bizarre). Then we check to see if that type is allowed in the restrictions, and if so, set it.
Conclusion
To quote Wikipedia in the above article:
Many programming techniques and data structures – including rope (data structure), lazy evaluation, class hierarchy (see below), arbitrary-precision arithmetic, CDR coding, the indirection bit and other kinds of tagged pointers, etc. – are usually implemented using some sort of tagged union.
Tagged unions are useful data types for systems such as artificial intelligence, where knowledge frames might be of many different types (coming from different systems).
This is part of the Phabstractic Library.
If you appreciate my programming please help support me through my Patreon.
photo credit: Biometric Bloodline via photopin (license)