۱۱ - ۱۰تایپهای جمع
حالا که آریتی ِ دادهسازها رو یاد گرفتیم، میتونیم جبر ِ نوعدادههای جبری رو تعریف کنیم. اول به تایپ جمع مثلِ Bool نگاه میکنیم:
data Bool = False | Trueقبلاً گفتیم که | فصل منطقی، یعنی یا رو نشون میده. این معادلِ جمع در نوعدادههای جبری ِه. برای پیدا کردنِ کاردینالیتی ِ تایپهای جمع، کاردینالیتی ِ دادهسازهاشون رو با هم جمع میکنیم. True و False هیچ آرگومانی نمیگیرن و در نتیجه سازندههای پوچگانه اند و هر کدوم فقط ارزشِ ۱ برای کاردینالیتی دارن.
حالا یه کم حساب کنیم. همونطور که گفتیم، در کاردینالیتی، سازندههای پوچگانه ۱ اند، و تایپهای جمع، + اند:
data Bool = False | TrueBool چندتا مقدار داره؟ دو تا دادهساز هستن که هر کدوم فقط یک مقدار رو ارائه میدن. با توجه به اینکه خط عمودی، جمع یا (+) رو نشون میده:
-- کاردینالیتی رو نشون میده ?? علامتِ
True | False = ??
True + False = ??
-- اند ۱ هر دو برابر True و False
1 + 1 == ??در نتیجه کاردینالیتی ِ Bool پیدا میشه:
1 + 1 == 2
-- Bool لیست همهی مقادیر ممکن برای
[True, False] -- ۲ لیست با طولتوی REPL هم میشه امتحان کرد:
Prelude> length (enumFrom False)
2با توجه به اینها، وقتی با یه مقدارِ Bool کار میکنیم باید دو مقدارِ ممکن رو در نظر بگیریم. تایپهای جمع در واقع راهی برای بیانِ چند حالتِ ممکن در داخلِ یک نوعداده اند.
اعداد صحیح ِ ۸-بیتی علامتدار در هسکل، همونطور که قبلاً دیدیم با نوعداده ِ Int8 که بازهای از ۱۲۸- تا ۱۲۷ داره تعریف میشن. اینطوری نیست، ولی میشه این نوعداده رو، تایپِ جمعی که از همهی اون ۲۵۶ عدد تشکیل شده فرض کرد (کاردینالیتی ِ۲۵۶).
تمرینها: دلسوزی برای بول
۱.
با نوعداده ِ زیر
data BigSmall =
Big Bool
| Small Bool
deriving (Eq, Show)کاردینالیتی ِ این نوعداده چیه؟ راهنمایی: کاردینالیتی ِ Bool رو میدونیم. مثل حل بالا جواب بدین.
۲.
با نوعداده ِ زیر
-- در گستره Int8 آوردن
import Data.Int
data NumberOrBool =
Numba Int8
| BoolyBool Bool
deriving (Eq, Show)
-- استفاده از پرانتز به خاطر
-- (-) تداخل گرامری بین
-- negate و تابع
let myNumba = Numba (-128)کاردینالیتی ِ NumberOrBool چیه؟ اگه سعی کنین یه Numba با لفظ ِ عددیِ بزرگتر از ۱۲۷ درست کنین چی میشه؟ یا لفظ ِ عددی کوچکتر از (۱۲۸-)؟
اگه دقیقاً از (-128) استفاده کنین، یه هشدار ِ بیجا میبینین:
Prelude> let n = Numba (-128)
Literal 128 is out of the
Int8 range -128..127
If you are trying to write a large negative
literal, use NegativeLiteralsاز اونجا که ۱۲۸- یه Int8 ِ کاملاً معتبره، میشه این هشدار رو نادیده گرفت. دلیل این پیغام اینه که وقتی (-128) به (negate 128) تلخ میشه، کامپایلر میبینه که برای تایپِ Int8 که حد بالاش عدد ۱۲۷ ِه، از عدد ۱۲۸ استفاده شده. کامپایلر هم قبل از اینکه منفی رو به ۱۲۸ اعمال کنه، فوراً به بزرگتر بودن ۱۲۸ از ۱۲۷ غُر میزنه. یه راه که این پیغام رو نگیرین اینه:
Prelude> let n = (-128)
Prelude> let x = Numba nیا مثل پیشنهاد خودش از توسعه ِ NegativeLiterals استفاده کنین:
Prelude> :set -XNegativeLiterals
Prelude> let n = Numba (-128)دقت کنین که استفاده از تابعِ negate با توسعه ِ لفظهای منفی باز هم اون هشدار رو میده.