Lesson 13 of 17

Generic Types

Type Parameters

Generic types let you write code that works with any type. You define them using type parameters in parentheses:

pub type Box(a) {
  Box(value: a)
}

The a is a type parameter. You can create boxes containing any type:

let int_box = Box(value: 42)         // Box(Int)
let str_box = Box(value: "hello")    // Box(String)

Generic Functions

Functions can also use type parameters:

fn identity(x: a) -> a {
  x
}

fn apply(value: a, f: fn(a) -> b) -> b {
  f(value)
}

The type parameter a means "any type." The compiler ensures consistency -- if a function takes a and returns a, both must be the same type.

Built-in Generic Types

Several built-in types are generic:

  • List(a) -- a list of any type
  • Result(value, error) -- success or failure with typed values
  • Option(a) -- a value that may or may not exist

Multiple Type Parameters

Types can have multiple parameters:

pub type Pair(a, b) {
  Pair(first: a, second: b)
}

let p = Pair(first: 1, second: "hello")  // Pair(Int, String)

Pattern Matching on Generic Types

Pattern matching works the same way with generic types:

fn unwrap_or(box: Box(a), default: a) -> a {
  case box {
    Box(value: v) -> v
  }
}

Your Task

Define a generic Wrapper type with a value field. Write a function wrap that takes a value and returns it wrapped, and a function map_wrapper that applies a function to the wrapped value. Use them to wrap an integer, double it, and print the result.

Gleam runtime loading...
Loading...
Click "Run" to execute your code.