ফ্যান্টম টাইপ হলো কোনো কাস্টম টাইপের এমন টাইপ প্যারামিটার, যা ওই টাইপের কোনো ভ্যালু কনস্ট্রাক্টরে ব্যবহৃত হয় না।
এটা একটু বিমূর্ত ব্যাপার, তাই চলুন একটি উদাহরণ দেখি:
pub type Length(unit) {
Length(amount: Float)
}
এই উদাহরণে unit টাইপ প্যারামিটারটি Length ভ্যালু কনস্ট্রাক্টরে ব্যবহৃত হয়নি, তাই unit একটি ফ্যান্টম টাইপ।
এই অব্যবহৃত টাইপ প্যারামিটারটি হয়তো অকেজো মনে হতে পারে, তবে 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 ফাংশনটি অন্য কোনো একক প্যারামিটারের দৈর্ঘ্য গ্রহণ করবে না; সঠিক এককই ব্যবহৃত হয়, তা নিশ্চিত করতে ফ্যান্টম টাইপটি কাজে লাগানো হয়েছে।
দুটি দৈর্ঘ্যের মান যেন একই এককের হয়, তা নিশ্চিত করতে উভয়ের জন্যই একই টাইপ ভ্যারিয়েবল ব্যবহার করে একটি ফাংশন লেখা যায়।
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.
ফ্যান্টম টাইপ ওপেক টাইপের সঙ্গে ভালোভাবে কাজ করতে পারে। অন্য মডিউলগুলো যদি Length মান তৈরি করতে না পারে, তাহলে আমরা নিশ্চিত করতে পারি যে অবৈধ একক টাইপ দিয়ে সেগুলো তৈরি করা যাবে না, আর সেগুলোর সঙ্গে কেবল উপরে ডিফাইন করা ফাংশনগুলোই ব্যবহার করা যাবে।