From f4ae307c5eb91e8f012f89eae076d91646cdb9b4 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Tue, 1 Apr 2025 16:19:40 +0000 Subject: [PATCH] Add Item Specifications --- Item-Specifications.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Item-Specifications.md diff --git a/Item-Specifications.md b/Item-Specifications.md new file mode 100644 index 0000000..9ec5b26 --- /dev/null +++ b/Item-Specifications.md @@ -0,0 +1,24 @@ +This page is devoted to concepts and designs for the structure of items in the TypeDispatcher and how they are specified. + +## Map-like object indexed by identifier and types + +In this concept, we think of the TypeDispatcher object `math` simply as a big map indexed by a string identifier and a list of types, with a handful of special properties: + +* The `math` object is set up so that you can write `math.foo(a, b, c)` to call `math['foo', [typeOf(a), typeOf(b), typeOf(c)]](a, b, c)`. +* The stored entities are "dependent objects" -- they record at their creation time what other entries of the TypeDispatcher object they depend on, and if any of those change, they are regenerated as needed. +* The keys and values of the `math` object can be specified in a pattern-matching style that supports/simulates generic functions + +How would this look in practice? Let's start by considering a `square` function that can operate on any type and depends on the `multiply` entry for that same type, and just calls that entry with both arguments set to the original single argument. We might specify this as: +``` +export const square = (math, [T]) => { + const mul = math.get('multiply', [T, T]) + return a => mul(a, a) +} +``` +Note that we should not write +``` +export const square = (math, [T]) => { + return a => math.multiply(a, a) +} +``` +That's because in order to work as a dependency, the dependent items must be extracted within the body of the function that provides the final behavior/value for the item, not within that behavior.