Traits: traits that require other traits

A trait may require another of every implementor, with a where clause
in the trait. The section shows a function that asks for one trait and
uses the other, and notes that Ord now requires Eq.

🤖 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-21 06:33:00 +02:00
parent 8729cb3ef7
commit 6d9c9bf8a0

View file

@ -2152,6 +2152,26 @@ A blanket implementation is one for a bare type variable. It applies to every ty
(weight "hello") ;; 5 (weight "hello") ;; 5
}| }|
@subsubsection{Traits that require other traits}
A trait may say that every type implementing it implements another trait too, with a @code{where} in the trait itself. Something that greets must have a name:
@codeblock[#:lang "bjolang"]|{
(def/trait (Named %a)
(: name-of (-> %a string)))
(def/trait (Greet %a)
(where (Named %a))
(: greeting (-> %a string)))
(: introduce (-> %a string) (where (Greet %a)))
(defun (introduce x) (str (name-of x) " says " (greeting x)))
}|
@code{introduce} asks only for @code{Greet}, and may still call @code{name-of}: a type that can greet is known to have a name. An implementation of @code{Greet} for a type with no @code{Named} is a compile error at the implementation.
The prelude's @code{Ord} requires @code{Eq} this way, so a function with @code{(where (Ord %a))} can use @code{=} as well as @code{compare}.
@subsubsection{Eq, Ord and ->str} @subsubsection{Eq, Ord and ->str}
Three traits from the prelude are worth knowing by heart, since the rest of the library leans on them. Three traits from the prelude are worth knowing by heart, since the rest of the library leans on them.