flan/test/programs/generic-reject.flan
Joseph Ferano dad725afe4 The prelude's per-type families collapse: 22 functions become 10, 27 become 16
swap!, reverse!, sort!, sort-by!, index-of, min-of, max-of, map!,
reduce and filter, each written once over $t. Every call site in the
corpus moves with them.

min-of and max-of are not min and max because min and max are builtins
over two or more numbers and nothing shadows a builtin. These reduce a
slice, which is a different operation at a different arity.

sort-bytes! did not collapse into sort!, and the reason is the point of
the predicates: a [u8] is not ordered? and cannot be, because < is an
instruction and comparing two slices lexicographically is a loop. It is
sort-by! with bytes<? written in, one line, keeping its name and its
stability note. sum-i32/sum-f32 and append-i64!/append-f64! stay for the
reasons the spike gave.

Not what the notes predicted: none of the ten collapses on a signature
change alone. filter and reduce need copyable? because the checker
demands it - reduce's accumulator at (Vec i32) is a double move - and
the rest declare it because a slice of owning elements would have them
duplicating headers.
2026-09-13 14:49:11 +07:00

16 lines
778 B
Plaintext

;;;; The refusal, at the definition and not at a call site.
;;;;
;;;; A generic body is checked once with its type variables abstract, so an
;;;; operator the variable is not declared to support is refused here, naming
;;;; the variable — rather than at whichever call site first instantiated it
;;;; at a type that did not work. That is not Odin's model: Odin checks a
;;;; polymorphic body only per instantiation, so (+ a b) over a $T compiles
;;;; there and fails only if someone reaches it at a type without +.
;;;;
;;;; The way out is either predicate — {:where (numeric? $t)} — or the
;;;; parameter, a (Fn [$t $t] $t) the caller supplies. Neither is written
;;;; here, which is the point.
(defn add2 [a $t b $t] $t (+ a b))
(defn main [] () (println (add2 1 2)))