Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions WYBE.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ It may contain the following sorts of items:
* [procedure definitions](#procedure-definitions),
* [constructor declarations](#constructor-declarations),
* [type declarations](#type-declarations),
* [trait declarations and implementations](#traits),
* [resource declarations](#resource-declarations), and
* [module declarations](#submodules).

Expand Down Expand Up @@ -1610,6 +1611,124 @@ two input lists must be the same, and the result will be a list of the same
type.


## <a name="traits"></a>Traits

A *trait* specifies operations that a type must provide. It lets a procedure
work with any type that has the required operations, while retaining static type
checking. Trait calls are dispatched to the implementation for the concrete
type supplied by the caller.

A module becomes a trait by containing a `trait` declaration. A trait cannot
also declare a representation or constructors. Its required operations are
declared with `abstract`:

```
# speaker.wybe
trait

abstract speak(x:_): string
```

An abstract declaration has the same prototype syntax as a procedure or
function declaration, but no body. It must be in a trait module, and it must
have exactly one type parameter constrained by that trait. In the example
above, `_` is inferred to be that constrained type. Writing the constraint
explicitly is useful when there is more than one type variable:

```
abstract speak(x:T<:_): string
```

The `T<:_` notation means that `T` may be any type that implements the current
trait. More generally, a type variable can be constrained by a named trait:

```
def speak_twice(x:T<:speaker): string = "$(speak(x)) $(speak(x))"
```

Trait constraints can be combined. Here `T` must implement both `speaker` and
`named`:

```
def describe_speaker(x:T<:{speaker, named}): string = describe(x)
```

Using a trait name directly as a parameter type is a shorthand for a type
variable constrained to that trait, so the first example could instead be
written as `def say(x:speaker): string = speak(x)`.

### Implementing a trait

Declare that the type defined by the current module implements a trait with:

> `impl` *trait*

For example, a `dog` type can implement `speaker` as follows:

```
# dog.wybe
use speaker

impl speaker

pub constructor dog(name:string)

pub def speak(x:_): string = "$(x^name) says woof"
```

Each abstract operation in `speaker` must have exactly one matching concrete
procedure or function for `dog`. Its parameter flows, argument and result
types, determinism, purity, and resource use must match the abstract
declaration. The compiler reports an error if a required operation is missing
or ambiguous.

An implementation for another type may be declared in any module with:

> `impl` *type* `<:` *trait*

For example, this makes `int` implement a trait declared in a submodule:

```
module printable {
trait
abstract render(x:T<:_): string
}

impl int <: printable

def render(x:int): string = "integer $x"
```

The implementation procedures are resolved in the module containing the
`impl` declaration. If there are matching procedures imported from elsewhere,
the local matching procedure is preferred.

### Default trait implementations

A trait may give an abstract operation a default implementation by declaring a
concrete procedure or function in the trait module with the same signature.
Types implementing the trait use that default unless their implementation
module supplies its own matching operation:

```
# greeter.wybe
trait

abstract greet(x:T<:_): string

pub def greet(x:_): string = "default greeting"

# silent.wybe
use greeter

constructor silent(x:int)
impl greeter
```

Here `greet(silent(42))` returns `"default greeting"`. A concrete implementation
in `silent` named `greet` with the matching signature overrides the default.


## <a name="resources"></a>Resources

Resources provide an alternative argument passing mechanism,
Expand Down
Loading