Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Traits

Traits are type constraints that define common behaviour.

A trait definition consists in a series of values declarations, where exactly one type variable is bound to a trait constraint:

trait Show {
  @type (a) -> String where a: Show
  let show
}

⚠️ NOTE: it's not possible to create user-defined traits yet. Currently built-in traits are: Show, Eq, Cmp and Ord.

Named types can then define their specialized implementation of each trait:

impl Show for List<a> where a: Show {
  let show = fn lst {
    // .. implementation
  }
}

You can then use the function defined in a trait with the values that implement it:

// the following is valid, because Int implements Show
show(42)

// the following is not, because `() -> Int` doesn't
show(fn { 0 })

Traits constraints are inferred automatically:

// inferred as: `(a) -> String where a: Show`
let my_fn = fn a {
  show(a)
}

but can also be specified manually with type hints:

@type (a) -> String where a: Show
let my_fn = // ..

Ambiguous check

Unlike interfaces of object oriented languages, traits are resolved during typechecking, not at runtime. You can see traits as implicitly passed arguments, resolved statically. As a consequence, in order not to have an ill-typed program, each trait boundary must appear in the top-level type, whether that's automatically inferred, or manually specified. For example, it's not possible to write the following:

// doesn't compile!
let ill_typed_fn = fn x {
  let _ = fn a { show(a) };
  x + 1
}

On the other hand, this means it's possible to write things that wouldn't be possible with interfaces based on runtime informations:

@type (String) -> Maybe<a> where a: FromJson
let parse = // ..

@type Maybe<List<Int>>
let my_value = parse("[1, 2, 3]")

Deriving

Some traits can be derived automatically by the compiler:

@deriving(Eq, Show, Cmp)
pub(..) type Some<a> {
  Some(a),
  None,
}

This will automatically create a trait implementation of the given traits

⚠️ NOTE: it's not possible to create user-defined traits implementations yet. You can only automatically derive (without the @derive annotation)