diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-07-08 22:06:05 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-07-08 22:06:05 -0400 |
| commit | 7fa325f583a59a1999cd8ce093a49f8048a3e05c (patch) | |
| tree | 5157b1cbd4af6318eb77b3fcf5d80420d0cba46d /doc/couple.md | |
| parent | 9ce4441a2fec2f6bd301f9cf5ad801c9534d34eb (diff) | |
Simplify and update Couple/Merge docs
Diffstat (limited to 'doc/couple.md')
| -rw-r--r-- | doc/couple.md | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/doc/couple.md b/doc/couple.md index e3823249..a360e693 100644 --- a/doc/couple.md +++ b/doc/couple.md @@ -25,7 +25,15 @@ Merge (`>`) takes one argument, but a nested one. `π©` is an array of arrays, β’ a β’ > a -Merge serves as a generalization of Solo and Couple, since Solo is `{>β¨π©β©}` and Couple is `{>β¨π¨,π©β©}`. Since `β` works on the "list" of arguments, it can only add one dimension, but `>` can take any number of dimensions as its input. +If `π©` is empty, but has a [fill](fill.md) element, then its shape is used for the inner shape. If it doesn't have a fill, the inner shape is assumed to be empty, so that the result is `π©` with no changes. + +Merge serves as a generalization of Solo and Couple, since Solo is `{>β¨π©β©}` and Couple is `{>β¨π¨,π©β©}`. These can be combined with [Pair](pair.md), giving `>β` for both. Since the result of `β` has rank 1, it can only add one dimension, but `>` can take any number of dimensions as its input. + +## Coupling units + +A note on the topic of Solo and Couple applied to [units](enclose.md#whats-a-unit). As always, one axis will be added, so that the result is a list (strangely, J's [laminate](https://code.jsoftware.com/wiki/Vocabulary/commaco#dyadic) differs from Couple in this one case, as it adds an axis to get a shape `2βΏ1` result). Solo on a unit is interchangeable with [Deshape](reshape.md) (`β₯`), and either primitive might be chosen for stylistic reasons. Couple on units is equivalent to [Join-to](join.md) (`βΎ`), but this is an irregular form of Join-to because it is the only case where Join-to adds an axis to both arguments instead of just one. Couple should be preferred in this case. + +As a consequence, [Pair](pair.md) (`β`) can be written `ββ<`, while `β` is `>ββ` as discussed above. This gives the neat (but not useful) identities `β ββ >βββ<`, and `β ββ >βββ<`, which have the same form because adding `β<` commutes with adding `>β`. ## Merge and array theory @@ -36,7 +44,7 @@ In all cases, what these functions do is more like reinterpreting existing data β₯ β₯Β¨ a βΎ β₯ β₯Β¨ a -Somewhat like [Table](map.md#table) `β`, Merge might be considered a fundamental way to build up multidimensional arrays from lists. In both cases rank-0 or [unit](enclose.md#whats-a-unit) arrays are somewhat special. They are the [identity value](fold.md#identity-values) of a function with Table, and [Enclose](enclose.md) (`<`), which creates a unit, is a right inverse to Merge. Enclose is needed because Merge can't produce a rank 0 array on its own. Merge has another catch as well: it can't produce arrays with a 0 in the shape, except at the end, without relying on a [fill](fill.md) element. +Somewhat like [Table](map.md#table) `β`, Merge might be considered a fundamental way to build up multidimensional arrays from lists. In both cases rank-0 or [unit](enclose.md#whats-a-unit) arrays are somewhat special. They are the [identity value](fold.md#identity-values) of a function with Table, and [Enclose](enclose.md) (`<`), which creates a unit, is a right inverse to Merge. Enclose is needed because Merge can't produce a rank 0 array on its own. Merge has another catch as well: it can't produce arrays with a 0 in the shape, except at the end, without relying on a fill element. β’ e β β¨β©Β¨ β3 β’ > e @@ -44,14 +52,8 @@ Somewhat like [Table](map.md#table) `β`, Merge might be considered a fundament Above we start with a list of three empty arrays. After merging once we get a shape `3βΏ0` array, sure, but what happens next? The shape added by another merge is the shared shape of that array's elementsβand there aren't any! If the nested list kept some type information around then we might know, but extra type information is essentially how lists pretend to be arrays. True dynamic lists simply can't represent multidimensional arrays with a 0 in the middle of the shape. In this sense, arrays are a richer model than nested lists. -## Coupling units - -A note on the topic of Solo and Couple applied to units. As always, one axis will be added, so that the result is a list (strangely, J's [laminate](https://code.jsoftware.com/wiki/Vocabulary/commaco#dyadic) differs from Couple in this one case, as it will add an axis to get a shape `2βΏ1` result). For Solo, this is interchangeable with [Deshape](reshape.md) (`β₯`), and either primitive might be chosen for stylistic reasons. For Couple, it is equivalent to [Join-to](join.md) (`βΎ`), but this is an irregular form of Join-to because it is the only case where Join-to adds an axis to both arguments instead of just one. Couple should be preferred in this case. - -The function [Pair](pair.md) (`β`) can be written `ββ<`, while `β` in either valence is `>ββ`. As an interesting consequence, `β ββ >βββ<`, and `β ββ >βββ<`. These two identities have the same form because adding `β<` commutes with adding `>β`. - ## Definitions -As discussed above, `β` is equivalent to `>{β¨π©β©;β¨π¨,π©β©}` or `>β`. To complete the picture we should describe Merge fully. Merge is defined on an array argument `π©` such that there's some shape `s` satisfying `β§Β΄β₯(sβ‘β’)Β¨π©`. If `π©` is empty then any shape satisfies this expression; `s` should be chosen based on known type information for `π©` or otherwise assumed to be `β¨β©`. If `s` is empty then `π©` is allowed to contain atoms as well as unit arrays, and these will be implicitly promoted to arrays by the `β` indexing used later. We construct the result by combining the outer and inner axes of the argument with Table; since the outer axes come first they must correspond to the left argument and the inner axes must correspond to the right argument. `π©` is a natural choice of left argument, and because no concrete array can be used, the right argument will be `βs`, the array of indices into any element of `π©`. To get the appropriate element corresponding to a particular choice of index and element of `π©` we should select using that index. The result of Merge is `π©βΛββs`. +We can define `β` as `>β`. To complete the picture we should describe Merge fully. Merge is defined on an array argument `π©` such that there's some shape `s` satisfying `β§Β΄β₯(sβ‘β’)Β¨π©`. If `π©` is empty then any shape satisfies this expression; `s` is then the shape of the [fill](fill.md) if there is one, or otherwise `β¨β©`. -Given this definition we can also describe Rank (`β`) in terms of Each (`Β¨`) and the simpler monadic function Enclose-Rank `<βk`. We assume effective ranks `j` for `π¨` (if present) and `k` for `π©` have been computed. Then the correspondence is `π¨Fβkπ© ββ >(<βjπ¨)FΒ¨(<βkπ©)`. +Then the result of Merge is `π©βΛββs`. Here, [Table](map.md#table) is a nice way of combining outer and inner axes to produce the result; since the outer axes come first they should go on the left and the inner axes on the right. `π©` is a natural choice of left argument, and because no concrete array can be used, the right argument is `βs`, the array of indices into any element of `π©`. Then [Pick](pick.md) selects all the elements. If `s` is empty, then `π©` is allowed to contain atoms as well as unit arrays. Pick will implicitly treat them as arrays. |
