Parcours
/
Gleam
Gleam
/
Exercices
/
Boutique de stickers
Boutique de stickers

Boutique de stickers

Exercice d'apprentissage

Introduction

Types fantômes

Les types fantômes sont des paramètres de type d'un type personnalisé qui ne sont utilisés dans aucun des constructeurs de valeurs de ce type.

C'est un peu abstrait, alors voici un exemple :

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

Dans cet exemple, le paramètre de type unit n'est pas utilisé dans le constructeur de valeurs Length, donc unit est un type fantôme.

Ce paramètre de type inutilisé peut sembler inutile, mais il permet d'ajouter d'autres restrictions sur la façon dont les valeurs Length peuvent être utilisées.

Par exemple, on pourrait avoir une fonction double, qui multiplie la longueur. Elle fonctionne avec des longueurs de n'importe quelle unité, donc le paramètre de type est une variable de type générique.

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

On pourrait aussi avoir une fonction add_inch, qui ne fonctionne que si la longueur est en pouces.

// 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)
}

La fonction add_inch n'acceptera pas de longueurs avec un autre paramètre d'unité : le type fantôme a été utilisé pour garantir que seule l'unité correcte est employée.

On peut aussi écrire une fonction qui garantit que deux valeurs de longueur ont la même unité, en utilisant la même variable de type pour les deux.

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.

Les types fantômes s'accordent bien avec les types opaques. Si les autres modules ne peuvent pas construire de valeurs Length, on peut alors garantir qu'elles ne sont pas construites avec un type d'unité invalide, et que seules les fonctions définies plus haut peuvent être utilisées avec elles.

Instructions

Lucy a une boutique de stickers en ligne, où elle vend de mignons stickers à l'effigie du langage de programmation préféré de chacun. Des gens du monde entier lui achètent ses stickers, et elle a quelques difficultés à gérer toutes ces devises différentes.

Crée un programme que Lucy peut utiliser pour calculer ses prix tout en étant sûre d'utiliser toujours la bonne devise.

1. Définis les types Usd, Eur et Jpy

Ces types servent à représenter les différentes devises que les clients de Lucy utilisent pour acheter ses stickers.

Ils doivent être utilisés comme des types fantômes et n'ont pas besoin d'avoir de constructeurs.

2. Définis le type Money

Le type Money doit avoir un champ Int pour le montant d'argent, un paramètre de type fantôme pour la devise, et il doit être un type opaque.

3. Définis les fonctions dollar, euro et yen

Définis les fonctions dollar, euro et yen qui prennent un argument Int et renvoient une valeur Money avec la bonne devise.

4. Définis la fonction total

Définis la fonction total qui prend un tableau de valeurs Money et renvoie le montant total d'argent dans le tableau.

total([euro(120), euro(200), euro(145)])
// -> euro(465)
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Gleam Exercism

Prêt à commencer Boutique de stickers ?

Inscris-toi sur Exercism pour apprendre et maîtriser Gleam avec 33 concepts122 exercices, et un vrai mentorat humain, le tout gratuitement.