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.