Track
/
Gleam
Gleam
/
Esercizi
/
Negozio di adesivi
Negozio di adesivi

Negozio di adesivi

Esercizio di apprendimento

Introduzione

Tipi fantasma

I tipi fantasma sono parametri di tipo di un tipo personalizzato che non vengono usati in nessuno dei costruttori di valore di quel tipo.

È un po' astratto, quindi ecco un esempio:

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

In questo esempio il parametro di tipo unit non viene usato nel costruttore di valore Length, quindi unit è un tipo fantasma.

Questo parametro di tipo inutilizzato può sembrare inutile, ma può servire ad aggiungere ulteriori restrizioni su come si possono usare i valori di Length.

Per esempio, potremmo avere una funzione double, che moltiplica la lunghezza. Funziona con lunghezze di qualsiasi unità, quindi il parametro di tipo è una variabile di tipo generica.

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

Potremmo anche avere una funzione add_inch, che funziona solo se la lunghezza è in pollici.

// 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 funzione add_inch non accetterà lunghezze con qualsiasi altro parametro di unità: il tipo fantasma è stato usato per garantire che venga usata solo l'unità corretta.

Si può anche scrivere una funzione che garantisca che due valori di lunghezza abbiano la stessa unità, usando la stessa variabile di tipo per entrambi.

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.

I tipi fantasma funzionano bene insieme ai tipi opachi. Se altri moduli non possono costruire valori di Length, allora possiamo garantire che non vengano costruiti con un tipo di unità non valido, e che con essi si possano usare solo le funzioni definite sopra.

Istruzioni

Lucy ha un negozio di adesivi online, dove vende adesivi carini che ritraggono i linguaggi di programmazione preferiti da tutti. Persone da tutto il mondo comprano i suoi adesivi e lei ha qualche difficoltà a gestire tutte le valute diverse.

Crea un programma che Lucy possa usare per calcolare i prezzi, avendo la certezza di usare sempre la valuta corretta.

1. Definisci i tipi Usd, Eur e Jpy

Questi tipi servono a rappresentare le diverse valute che i clienti di Lucy usano per comprare i suoi adesivi.

Vanno usati come tipi fantasma e non devono avere alcun costruttore.

2. Definisci il tipo Money.

Il tipo Money dovrebbe avere un campo Int per la quantità di denaro, un parametro di tipo fantasma per la valuta ed essere un tipo opaco.

3. Definisci le funzioni dollar, euro e yen

Definisci le funzioni dollar, euro e yen che accettano un argomento Int e restituiscono un valore Money con la valuta corretta.

4. Definisci la funzione total

Definisci la funzione total che prende un array di valori Money e ne restituisce l'importo totale.

total([euro(120), euro(200), euro(145)])
// -> euro(465)
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Gleam Exercism

Vuoi iniziare Negozio di adesivi?

Iscriviti a Exercism per imparare e padroneggiare Gleam con 33 concetti122 esercizi e il mentoring di persone reali, tutto gratis.