Tracks
/
Gleam
Gleam
/
Übungen
/
Sticker-Shop
Sticker-Shop

Sticker-Shop

Lernübung

Einführung

Phantomtypen

Phantomtypen sind Typparameter eines benutzerdefinierten Typs, die in keinem der Wertkonstruktoren dieses Typs verwendet werden.

Das ist etwas abstrakt, deshalb folgt hier ein Beispiel:

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

In diesem Beispiel wird der Typparameter unit nicht im Wertkonstruktor Length verwendet, also ist unit ein Phantomtyp.

Dieser ungenutzte Typparameter mag nutzlos erscheinen, aber er kann verwendet werden, um weitere Einschränkungen dafür hinzuzufügen, wie Length-Werte verwendet werden können.

Zum Beispiel könnten wir eine Funktion double haben, die die Länge multipliziert. Sie funktioniert mit Längen jeder Einheit, also ist der Typparameter eine generische Typvariable.

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

Wir könnten auch eine Funktion add_inch haben, die nur funktioniert, wenn die Länge in Zoll ist.

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

Die Funktion add_inch akzeptiert keine Längen mit einem anderen Einheitenparameter; der Phantomtyp wurde verwendet, um sicherzustellen, dass nur die richtige Einheit verwendet wird.

Eine Funktion kann auch so geschrieben werden, dass sie sicherstellt, dass zwei Längenwerte dieselbe Einheit haben, indem für beide dieselbe Typvariable verwendet wird.

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.

Phantomtypen lassen sich gut mit opaken Typen kombinieren. Wenn andere Module keine Length-Werte konstruieren können, können wir sicherstellen, dass sie nicht mit einem ungültigen Einheitentyp konstruiert werden und dass nur die oben definierten Funktionen mit ihnen verwendet werden können.

Anleitung

Lucy hat einen Online-Shop für Sticker, in dem sie niedliche Sticker verkauft, auf denen die Lieblingsprogrammiersprachen aller Leute zu sehen sind. Menschen aus aller Welt kaufen ihre Sticker, und sie hat Schwierigkeiten, mit all den verschiedenen Währungen umzugehen.

Erstelle ein Programm, mit dem Lucy Preise berechnen kann und dabei sicher sein kann, dass sie immer die richtige Währung verwendet.

1. Definiere die Typen Usd, Eur und Jpy

Diese Typen werden verwendet, um die verschiedenen Währungen darzustellen, die Lucys Kundinnen und Kunden zum Kauf ihrer Sticker verwenden.

Sie sollen als Phantomtypen verwendet werden und brauchen keine Konstruktoren zu haben.

2. Definiere den Typ Money.

Der Typ Money sollte ein Int-Feld für den Geldbetrag und einen Phantomtyp-Parameter für die Währung haben; außerdem sollte er ein opaker Typ sein.

3. Definiere die Funktionen dollar, euro und yen

Definiere die Funktionen dollar, euro und yen, die ein Int-Argument entgegennehmen und einen Money-Wert mit der richtigen Währung zurückgeben.

4. Definiere die Funktion total

Definiere die Funktion total, die eine Liste von Money-Werten entgegennimmt und den Gesamtbetrag des Geldes in der Liste zurückgibt.

total([euro(120), euro(200), euro(145)])
// -> euro(465)
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Gleam Exercism

Bereit, mit Sticker-Shop zu starten?

Melde dich bei Exercism an, um Gleam mit 33 Konzepte122 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.