From 6d9c9bf8a0ae4947242a791bbda9985f0f0bcf0153f71ef29a8fe0581b664d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Bj=C3=B6rnstam?= Date: Wed, 21 Oct 2026 06:33:00 +0200 Subject: [PATCH] Traits: traits that require other traits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- _01.Language-basics.sz | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/_01.Language-basics.sz b/_01.Language-basics.sz index 14b9eff..87d6a59 100644 --- a/_01.Language-basics.sz +++ b/_01.Language-basics.sz @@ -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.