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
}|
@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}
Three traits from the prelude are worth knowing by heart, since the rest of the library leans on them.