# `Feel.Analysis.Images.List`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/analysis/images/list.ex#L1)

The rules for the list built-ins (`Feel.Analysis.Images`, D-161, step C): the 24 functions of `Feel.Builtin.List`.

A rule gives the whole type of the result from the types of the arguments, `Null` included, and is held to the run
(`Feel.ImageCheck`, `test/feel/analysis/images/list_test.exs`). What a rule builds on is the way an argument is a list
(section 10.3.2.9.4): a list is itself, a value that is not one is the list of it, and `null` is no list, so the call is
`null`. The type of an argument is read as that (`read/1`): the types of its elements, and how many it has, which is none
(`empty list`), one (a value that is not a list), one or more (`non-empty list<...>`, D-152), or any number.

| Function | The type of the result |
| -------- | ---------------------- |
| `count` | `0` for the empty list, `1` for a value that is no list, `[1..max]` for a list that has an element; never `null` for a list |
| `reverse`, `distinct values` | the same elements, and the list that has an element stays one |
| `flatten` | the elements of the lists among the elements, to a depth of 16; has an element if no element can be a list |
| `append`, `concatenate`, `union` | the elements of the arguments, and of the items; has an element if an item is put in or an argument has one |
| `insert before`, `list replace`, `sublist` | a list that has an element: a position that is right for a list is one for a list that has an element |
| `remove` | the elements of the list (a list of one item has none left); `[]` for a value that is no list |
| `sort`, `list replace` with a function | the elements of the list, the same number of them |
| `index of` | `list<number in [1..max]>`, the empty list if nothing can be equal |
| `list contains` | `boolean`, `false` if nothing can be equal or the list is empty |
| `sum`, `mean`, `median`, `product` | a number (the item itself for a value that is no list; `a + b` for `sum(a, b)`, and so on, with the sets) |
| `stddev` | a number from 0 on; always `null` for a list, which may have fewer than two items |
| `mode` | the list of the numbers, with an element if the list has one |
| `max`, `min` | an element of one ordered kind (D-152), or `Null` |
| `all`, `any` | the booleans that the items allow |

## When the call is `null`

A `null` is in the type only if some arguments of the types give it (D-161):

  * the argument that is a list is `null`, or is the empty list where the function needs an item (`sum([])`, `max([])`,
    `insert before([], 1, x)`, `stddev([x])`);
  * an item is not of the kind the function wants (`sum(["a"])`, `all([1])`, `max([1, "a"])`, a `null` among the numbers,
    `[true, null]` for `all`);
  * a position that is not right for a list: `0`, past the end, `null`, or not a number. A list has any length and a type
    does not say it, so a position is right for every list that has an element only if it is cut to `1` or `-1` (a fraction
    is cut off toward zero: `[1..2)` and `(-2..-1]`); one that is cut to `0` is right for none. A `sublist` of a length
    takes it in the same way, and the length that is right for every list is `1`;
  * the arithmetic of the numbers fails (see below);
  * a function argument (`sort`, `list replace`) that is not a function of two parameters that gives a boolean.

Callback acceptance uses observable runtime arrows, not call refinements. These arrows guarantee
signatures, but do not exhaust them: a three-argument function type can hold a value that also has
a two-argument Boolean signature. Without such a guaranteed signature, a function remains a
possible callback and possible rejection. An excluded function is classified through its positive base.

## The arithmetic of a list of numbers

The count of a list is not in its type, so the sums and products of a list are those of lists of every length up to
`@most_items` (1E+18, what `Feel.Builtin.Arguments` calls past the end of anything a run can build):

  * **`sum`** overflows if 1E+18 times the largest number, or the least, is out of range: the list of the largest number
    twice does, and no list of `[0..150]` does.
  * **`mean`** is the sum, and a division by the count, which is `null` for a result too small to write (D-161): when the
    total can be near zero and not zero. Numbers are multiples of 1E-6176, so the mean of `0` and `1E-6176` is `null`, as is
    that of `-1`, `1` and `1E-6176`; a set of numbers that stay away from zero (`[0.001..150]`) never is.
  * **`median`** of an even count is the mean of the two in the middle: the sum of two, and the division by 2.
  * **`product`** of a list overflows or is too small to write unless all the numbers are `-1`, `0` or `1`.
  * **`stddev`** of two items or more is `null` for a sum or a square out of range, and for the square of a difference too
    small to write, which an item near zero has when the mean is near zero too.

The sets of the numbers are kept for what is exact and the kind is the type of the rest, which is broader and so sound: the
set of the sum of a list is not worked out, that of a few items given as arguments is (`sum(a, b)` is `a + b`, `mean(a, b)`
the sum divided by 2). The search for the arithmetic that fails is by the bounds and the neighbourhood of zero of the sets,
and is broader than the run for sets that are not intervals of numbers away from zero (it may say `Null` for a set of one
number near zero, which no list gives), never narrower.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
