Τα phantom types είναι παράμετροι τύπου ενός προσαρμοσμένου τύπου που δεν χρησιμοποιούνται σε κανέναν από τους κατασκευαστές τιμών αυτού του τύπου.
Αυτό είναι λίγο αφηρημένο, οπότε ας δούμε ένα παράδειγμα:
pub type Length(unit) {
Length(amount: Float)
}
Σε αυτό το παράδειγμα, η παράμετρος τύπου unit δεν χρησιμοποιείται στον κατασκευαστή τιμών Length, οπότε το unit είναι ένα phantom type.
Αυτή η αχρησιμοποίητη παράμετρος τύπου μπορεί να φαίνεται άχρηστη, αλλά μπορεί να χρησιμοποιηθεί για να προσθέσει περισσότερους περιορισμούς στον τρόπο που μπορούν να χρησιμοποιηθούν οι τιμές Length.
Για παράδειγμα, θα μπορούσαμε να έχουμε μια συνάρτηση double, η οποία πολλαπλασιάζει το μήκος. Λειτουργεί με μήκη οποιασδήποτε μονάδας, οπότε η παράμετρος τύπου είναι μια γενικευμένη μεταβλητή τύπου.
// This function accepts all Length values
pub fn double(length: Length(unit)) -> Length(unit) {
Length(length.amount *. 2.0)
}
Θα μπορούσαμε επίσης να έχουμε μια συνάρτηση add_inch, η οποία λειτουργεί μόνο αν το μήκος είναι σε ίντσες.
// 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)
}
Η συνάρτηση add_inch δεν θα δεχτεί μήκη με οποιαδήποτε άλλη παράμετρο μονάδας· το phantom type έχει χρησιμοποιηθεί για να διασφαλίσει ότι χρησιμοποιείται μόνο η σωστή μονάδα.
Μια συνάρτηση μπορεί επίσης να γραφτεί ώστε να διασφαλίζει ότι δύο τιμές μήκους έχουν την ίδια μονάδα, χρησιμοποιώντας την ίδια μεταβλητή τύπου και για τις δύο.
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.
Τα phantom types συνεργάζονται καλά με τους αδιαφανείς τύπους. Αν άλλα αρθρώματα δεν μπορούν να κατασκευάσουν τιμές Length, τότε μπορούμε να διασφαλίσουμε ότι δεν κατασκευάζονται με μη έγκυρο τύπο μονάδας, και ότι μόνο οι συναρτήσεις που ορίστηκαν παραπάνω μπορούν να χρησιμοποιηθούν με αυτές.
Η Lucy έχει ένα ηλεκτρονικό κατάστημα με αυτοκόλλητα, όπου πουλάει χαριτωμένα αυτοκόλλητα με τις αγαπημένες γλώσσες προγραμματισμού όλων. Άνθρωποι από όλο τον κόσμο αγοράζουν τα αυτοκόλλητά της και δυσκολεύεται λίγο να τα βγάλει πέρα με όλα τα διαφορετικά νομίσματα.
Δημιούργησε ένα πρόγραμμα που μπορεί να χρησιμοποιήσει η Lucy για να υπολογίζει τιμές, έχοντας πάντα τη βεβαιότητα ότι χρησιμοποιεί το σωστό νόμισμα.
Usd, Eur και Jpy
Αυτοί οι τύποι χρησιμοποιούνται για να αναπαραστήσουν τα διαφορετικά νομίσματα που χρησιμοποιούν οι πελάτες της Lucy για να αγοράσουν τα αυτοκόλλητά της.
Πρόκειται να χρησιμοποιηθούν ως phantom τύποι και δεν χρειάζεται να έχουν κανέναν κατασκευαστή.
Money.Ο τύπος Money πρέπει να έχει ένα πεδίο Int για το ποσό των χρημάτων, μια παράμετρο phantom τύπου για το νόμισμα, και πρέπει να είναι αδιαφανής τύπος.
dollar, euro και yen
Όρισε τις συναρτήσεις dollar, euro και yen, οι οποίες δέχονται ένα όρισμα Int και επιστρέφουν μια τιμή Money με το σωστό νόμισμα.
total
Όρισε τη συνάρτηση total, η οποία δέχεται μια λίστα με τιμές Money και επιστρέφει το συνολικό ποσό των χρημάτων στη λίστα.
total([euro(120), euro(200), euro(145)])
// -> euro(465)
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Gleam με 33 έννοιες122 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.