Traits: implementations for particular type arguments

One type may have an implementation at (List int) and another at
(List string). The section says how the compiler picks one, and that
overlapping implementations and calls at a type it cannot decide are
errors.

🤖 Generated with [ECA](https://eca.dev) (anthropic/claude-opus-5-5)

Co-Authored-By: eca-agent <git@eca.dev>
This commit is contained in:
Linus Björnstam 2026-10-20 22:15:21 +02:00
parent cefa2313ad
commit 8729cb3ef7

View file

@ -2101,6 +2101,28 @@ A trait has exactly one implementor type. When a method needs another type that
This is how the prelude's own @code{Iterable}, @code{Collection} and @code{Refable} work, and why @code{length} and @code{fold} work on so many types.
@subsubsection{Implementations for particular type arguments}
An implementation may be written for a generic type at particular type arguments, and one type may have several, one for each:
@codeblock[#:lang "bjolang"]|{
(impl (Describe (List int))
(defun (describe xs) "some numbers"))
(impl (Describe (List string))
(defun (describe xs) "some words"))
(describe (list 1 2)) ;; "some numbers"
(describe (list "a" "b")) ;; "some words"
}|
The compiler picks the one whose arguments match. Two rules keep that choice unambiguous:
@itemlist[
@item{Two implementations may not overlap. With @code{(List int)} already there, @code{(impl (Describe (List %a)) ...)} is refused, since a @code{(List int)} would then have two.}
@item{The type has to be known where the call is. @code{(describe (list))} is an error, because an empty list could be either, and so is a call at @code{(List %a)} in a generic function: neither implementation is written for every element type. Give such a value an annotation, or write one implementation for @code{(List %a)} with a @code{where}, as in the next section.}
]
@subsubsection{Conditional and blanket implementations}
An implementation for a generic type can require something of its type variables, with a @code{where} after the head. A list can be described if its elements can:
@ -2114,7 +2136,7 @@ An implementation for a generic type can require something of its type variables
(describe (list Clubs Hearts)) ;; "clubs, hearts"
}|
A blanket implementation is one for a bare type variable. It applies to every type that has no implementation of its own, and a more specific implementation always wins over it. Only the module that declares a trait may write its blanket:
A blanket implementation is one for a bare type variable. It applies to every type that has no implementation of its own, and a more specific implementation always wins over it. A type whose head has implementations only for other arguments, such as a @code{(List bool)} beside the @code{(List int)} above, is an error rather than the blanket. Only the module that declares a trait may write its blanket:
@codeblock[#:lang "bjolang"]|{
(def/trait (Weight %a)