# `ShotDs.Data.TypeScheme`
[🔗](https://github.com/jcschuster/ShotDs/blob/v1.2.1/lib/shot_ds/data/type_scheme.ex#L1)

Represents a rank-1 polymorphic type scheme:

$$\forall \alpha_1\dots\alpha_n.\, \tau$$

The quantified variables in `vars` are type variable references which appear
inside the body type and are universally quantified at the outermost level
(prenex form).

At each use site, schemes are *instantiated* into fresh monotypes via
`instantiate/1`, which replaces every quantified variable with a fresh
reference. This is the mechanism that allows polymorphic constants like
$=^\alpha$ (with scheme $\forall\alpha.\,\alpha\to\alpha\to o$) to be used at
different types within the same formula.

Monotypes can be lifted into trivial schemes (with empty `vars`) using
`mono/1`.

## Example

    iex> alpha = make_ref()
    iex> scheme = TypeScheme.new([alpha], Type.new(alpha, alpha))
    iex> match?(%TypeScheme{vars: [^alpha]}, scheme)
    true

# `t`

```elixir
@type t() :: %ShotDs.Data.TypeScheme{
  body: ShotDs.Data.Type.t(),
  vars: [ShotDs.Data.Type.variable_id()]
}
```

Elixir type of a (rank-1 polymorphic) type scheme.

# `free_type_vars`

```elixir
@spec free_type_vars(t()) :: MapSet.t(ShotDs.Data.Type.variable_id())
```

Returns the set of free type variables in the scheme. This is defined as the
set of free type variables in the body without the bound type variables.

# `generalize`

```elixir
@spec generalize(ShotDs.Data.Type.t(), MapSet.t(ShotDs.Data.Type.variable_id())) ::
  t()
```

Generalizes a given type by binding free type variables in a scheme.

# `instantiate`

```elixir
@spec instantiate(t()) :: ShotDs.Data.Type.t()
```

Instantiates the bound type variables in the given type scheme with fresh type
variables.

# `instantiate_with_refs`

```elixir
@spec instantiate_with_refs(t()) :: {ShotDs.Data.Type.t(), [reference()]}
```

Like `instantiate/1`, but also returns the list of fresh type-variable
references created for each bound variable (in order). Used by the TH1
formula parser to track which fresh refs correspond to the type parameters
so they can be unified with explicit type arguments during type erasure.

# `mono`

```elixir
@spec mono(ShotDs.Data.Type.t()) :: t()
```

Constructs a trivial type scheme representing the given monotype.

# `new`

```elixir
@spec new([ShotDs.Data.Type.variable_id()], ShotDs.Data.Type.t()) :: t()
```

Constructs a type scheme binding the type variables `vars` in the (possibly
polymorphic) type `body`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
