«نوع فانتوم» پارامتر نوعی از یک نوع سفارشی است که در هیچیک از سازندههای مقدار آن نوع به کار نمیرود.
این کمی انتزاعی است، پس بیایید با یک مثال روشنش کنیم:
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 را بسازند، آنگاه میتوان تضمین کرد که آنها با واحد نامعتبر ساخته نمیشوند و فقط توابع تعریفشده در بالا میتوانند با آنها به کار روند.
لوسی یک فروشگاه آنلاین برچسب دارد که در آن برچسبهای بامزهای میفروشد که زبانهای برنامهنویسی محبوب همه را به تصویر میکشند. آدمهایی از سراسر جهان برچسبهای او را میخرند و او در سر و کله زدن با این همه ارز مختلف کمی مشکل دارد.
برنامهای بنویسید که لوسی بتواند با آن قیمتها را حساب کند و در همان حال مطمئن باشد که همیشه از ارز درست استفاده میکند.
Usd، Eur و Jpy
این نوعها برای نمایش ارزهای مختلفی به کار میروند که مشتریهای لوسی با آنها برچسبهایش را میخرند.
قرار است به عنوان نوعهای فانتوم استفاده شوند و نیازی به داشتن هیچ سازندهای ندارند.
Money
نوع Money باید یک فیلد Int برای مقدار پول و یک پارامتر نوع فانتوم برای ارز داشته باشد و باید یک «نوع مات» باشد.
dollar، euro و yen
توابع dollar، euro و yen را تعریف کنید که یک آرگومان Int میگیرند و یک مقدار Money با ارز درست برمیگردانند.
total
تابع total را تعریف کنید که فهرستی از مقدارهای Money میگیرد و مجموع مقدار پول در فهرست را برمیگرداند.
total([euro(120), euro(200), euro(145)])
// -> euro(465)