Tipos fantasma são parâmetros de tipo de um tipo personalizado que não são usados em nenhum dos construtores de valores desse tipo.
Isso é um pouco abstrato, então 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, então unit é um tipo fantasma.
Esse parâmetro de tipo não utilizado pode parecer inútil, mas ele pode ser usado para adicionar mais restrições sobre como valores Length podem ser usados.
Por exemplo, poderíamos ter uma função double, que multiplica o comprimento. Ela funciona com comprimentos de qualquer unidade, então 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 poderíamos 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 aceitará comprimentos de qualquer outro parâmetro de unidade. O tipo fantasma foi usado para garantir que apenas a unidade correta seja usada.
Uma função também pode ser escrita para garantir que dois valores de comprimento sejam 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.
Tipos fantasma podem funcionar bem com tipos opacos. Se outros módulos não puderem construir valores Length, podemos garantir que eles não sejam construídos com um tipo de unidade inválido, e que apenas as funções definidas acima possam ser usadas com eles.
Lucy tem uma loja de adesivos online, onde vende adesivos fofos com as linguagens de programação favoritas de todo mundo. Pessoas do mundo todo compram os adesivos dela, e ela está tendo dificuldade para lidar com todas as moedas diferentes.
Crie um programa que Lucy possa usar para calcular preços, garantindo que ela esteja sempre usando a moeda correta.
Usd, Eur e Jpy
Esses tipos são usados para representar as diferentes moedas que os clientes de Lucy usam para comprar os adesivos dela.
Eles devem ser usados como tipos fantasma e não precisam ter construtores.
Money.O tipo Money deve ter um campo Int para a quantidade de dinheiro, um parâmetro de tipo fantasma para a moeda, e deve ser um tipo opaco.
dollar, euro e yen
Defina as funções dollar, euro e yen, que recebem um argumento Int e retornam um valor Money com a moeda correta.
total
Defina a função total, que recebe uma lista de valores Money e retorna o valor total de dinheiro na lista.
total([euro(120), euro(200), euro(145)])
// -> euro(465)
Crie sua conta no Exercism para aprender e dominar Gleam com 33 conceitos122 exercícios e mentoria humana de verdade, tudo de graça.