    "Given a nonempty stream of [[Summable]] values, return the
     sum of the values.

         {Float+} values = ... ;
         Float total = sum(values);

     For the case of a possibly-empty stream, form a nonempty
     stream starting with the zero element (the [[additive
     identity|Summable]]).

         {Float*} values = ... ;
         Float total = sum { 0.0, *values };

     For the case of a stream of `Integer`s, `Float`s, or
     `String`s, prefer [[Integer.sum]], [[Float.sum]], or
     [[String.sum]]."
    see (`function product`,
         `function Integer.sum`,
         `function Float.sum`,
         `function String.sum`)
    tagged("Streams", "Numbers")
    shared native Value sum<Value>({Value+} values)
            given Value satisfies Summable<Value>;

    shared native("js") Value sum<Value>({Value+} values)
            given Value satisfies Summable<Value> {
        value it = values.iterator();
        assert (!is Finished first = it.next());
        variable value sum = first;
        while (!is Finished val = it.next()) {
            sum += val;
        }
        return sum;
    }

    shared native("jvm") Value sum<Value>({Value+} values)
            given Value satisfies Summable<Value> {
        value it = values.iterator();
        switch (first = it.next())
        case (is Integer) {
            // unbox; don't infer type Value&Integer
            variable Integer sum = first;
            while (is Integer val = it.next()) {
                Integer unboxed = val;
                sum += unboxed;
            }
            assert (is Value result = sum);
            return result;
        }
        case (is Float) {
            // unbox; don't infer type Value&Float
            variable Float sum = first;
            while (is Float val = it.next()) {
                Float unboxed = val;
                sum += unboxed;
            }
            assert (is Value result = sum);
            return result;
        }
        case (is String) {
            value sum = StringBuilder();
            sum.append(first);
            while (is String val = it.next()) {
                sum.append(val);
            }
            assert (is Value result = sum.string);
            return result;
        }
        case (is Finished) {
            assert (false);
        }
        else {
            variable value sum = first;
            while (!is Finished val = it.next()) {
                sum += val;
            }
            return sum;
        }
    }