Percursos
/
Gleam
Gleam
/
Programa
/
Tipos fantasma
Ti

Tipos fantasma em Gleam

1 exercício

Sobre Tipos fantasma

Os tipos fantasma são parâmetros de tipo de um tipo personalizado que não são usados em nenhum dos construtores de valor desse tipo.

Isto é um pouco abstrato, por isso aqui está um exemplo:

pub type Length(unit) {
  Length(amount: Float)
}

Neste exemplo, o parâmetro de tipo unit não é usado no construtor de valor Length, por isso unit é um tipo fantasma.

Este parâmetro de tipo que não é usado pode parecer inútil, mas pode servir para acrescentar mais restrições à forma como os valores Length podem ser usados.

Por exemplo, podemos ter uma função double, que multiplica o comprimento. Funciona com comprimentos de qualquer unidade, por isso o parâmetro de tipo é uma variável de tipo genérica.

// This function accepts all Length values
pub fn double(length: Length(unit)) -> Length(unit) {
  Length(length.amount *. 2.0)
}

Também podemos ter uma função add_inch, que só funciona se o comprimento estiver em polegadas.

// A unit type for inches. It is never constructed so we don't
// define any constructors for it.
pub type Inches

pub fn add_inch(length: Length(Inches)) -> Length(Inches) {
  Length(length.amount +. 1.0)
}

A função add_inch não aceita comprimentos com qualquer outro parâmetro de unidade; o tipo fantasma foi usado para garantir que só é usada a unidade correta.

Também se pode escrever uma função que garanta que dois valores de comprimento são da mesma unidade, usando a mesma variável de tipo para ambos.

pub fn add(a: Length(unit), b: Length(unit)) -> Length(unit) {
  Length(a.amount +. b.amount)
}
let two_meters: Length(Meters) = Length(2.0)
let two_inches: Length(Inches) = Length(2.0)

add(two_meters, two_meters)
// -> Length(4.0): Length(Meters)

add(two_meters, two_inches)
// Type error! The unit type parameters do not match.

Os tipos fantasma dão-se bem com tipos opacos. Se os outros módulos não conseguirem construir valores Length, podemos garantir que não são construídos com um tipo de unidade inválido e que só se podem usar com eles as funções definidas acima.

Editar via GitHub A ligação abre numa nova janela ou separador

Aprende Tipos fantasma