MoonBit Language Tour MoonBit

Trait Bounds

Previously we introduced how to write a generic function swap:

fn[T] swap(arr : Array[T]) -> Unit {
  let tmp : T = arr[0]
  arr[0] = arr[1]
  arr[1] = tmp
}

The swap function only reorders elements in the array; it cannot perform any operation on the elements themselves. This is because T is completely unknown inside swap: we do not know which methods T supports, such as comparing two elements for equality or printing a value for debugging.

We can attach trait bounds to T using a type‑like annotation. The syntax T : Eq means that T must implement the Eq trait. A generic parameter can have multiple bounds, for example T : Eq + Show means T must implement both Eq and Show. This guarantees that we can safely call the methods of those traits in the function body.

The example changes the behavior of swap: before swapping the elements it prints debug information. The Show trait provides a to_string method, so we can call to_string on values of type T to convert them to strings, or use them directly in string interpolation.

The example also includes a find_index function that tries to locate an element in an array. If found, it returns the index; otherwise it returns None. To compare array elements with the target element, we add the Eq trait bound to the generic parameter T, allowing us to call Eq::equal for the comparison.

///|
fn[T : Show] swap(arr : Array[T]) -> Unit {
  let tmp_str = arr[0].to_string()
  let arr1_str = arr[1].to_string()
  println("swap \{tmp_str} and \{arr1_str} in array.")
  // Same as above:
  // println("swap \{arr[0]} and \{arr[1]} in array.") 
  let tmp : T = arr[0]
  arr[0] = arr[1]
  arr[1] = tmp
}

///|
fn[T : Eq + Show] find_index(array : Array[T], target : T) -> Int? {
  for index, elem in array {
    if Eq::equal(elem, target) {
      println("array[\{index}] = \{elem}, \{elem} == \{target}")
      return Some(index)
    } else {
      println("array[\{index}] = \{elem}, \{elem} != \{target}")
    }
  }
  return None
}

///|
fn main {
  let ints = [2, 1, 3, 4, 5]
  swap(ints)
  let j = find_index(ints, 4)
  println("the result is \{j}")
  let i = find_index([true, false, true, false], false)
  println("the result is \{i}")
}