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:
parent
cefa2313ad
commit
8729cb3ef7
1 changed files with 23 additions and 1 deletions
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue