Percursos
/
Gleam
Gleam
/
Exercícios
/
Loja de Autocolantes
Loja de Autocolantes

Loja de Autocolantes

Exercício de aprendizagem

Introdução

Tipos fantasma

Os tipos fantasma são parâmetros de tipo de um tipo personalizado que não são utilizados em nenhum dos construtores de valores 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 é utilizado no construtor de valores Length, por isso unit é um tipo fantasma.

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

Por exemplo, podíamos 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 podí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 aceita comprimentos com qualquer outro parâmetro de unidade. O tipo fantasma foi usado para garantir que apenas a unidade correta é utilizada.

Também podemos 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 podem funcionar bem com tipos opacos. Se 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ó as funções definidas acima podem ser usadas com eles.

Instruções

A Lucy tem uma loja de autocolantes online, onde vende autocolantes giros com as linguagens de programação preferidas de toda a gente. Pessoas de todo o mundo compram-lhe os autocolantes e ela está a ter dificuldades em lidar com as diferentes moedas.

Cria um programa que a Lucy possa usar para calcular preços e ter a certeza de que está sempre a usar a moeda correta.

1. Define os tipos Usd, Eur e Jpy

Estes tipos servem para representar as diferentes moedas que os clientes da Lucy usam para comprar os autocolantes dela.

Devem ser usados como tipos fantasma e não precisam de ter construtores.

2. Define o tipo Money.

O tipo Money deve ter um campo Int para a quantia de dinheiro, um parâmetro de tipo fantasma de moeda e deve ser um tipo opaco.

3. Define as funções dollar, euro e yen

Define as funções dollar, euro e yen que recebem um argumento Int e devolvem um valor Money com a moeda correta.

4. Define a função total

Define a função total, que recebe uma lista de valores Money e devolve a quantia total de dinheiro na lista.

total([euro(120), euro(200), euro(145)])
// -> euro(465)
Editar via GitHub A ligação abre numa nova janela ou separador
Gleam Exercism

Estás pronto para começar Loja de Autocolantes?

Inscreve-te no Exercism para aprenderes e dominares Gleam com 33 conceitos122 exercícios, e mentoria humana real, tudo grátis.