۴ - ۵مقایسهی مقادیر
تا اینجا بیشترِ عملیاتی که با اعداد داشتیم محاسبات بودن. اعداد رو میشه برای تساوی، بزرگتر بودن، یا کوچکتر بودن هم مقایسه کرد:
Prelude> let x = 5
Prelude> x == 5
True
Prelude> x == 6
False
Prelude> x < 7
True
Prelude> x > 3
True
Prelude> x /= 5
False
دقت کنید که در خط اول با یک علامت تساوی مقداری برای x
تعریف کردیم. پس میدونیم که تا آخر این جلسه ِوREPL همهی x
ها مقدارِ ۵ دارن. چونکه از علامت تساوی برای تعاریف استفاده شده، برای آیا مساوی هست با باید از دو تا علامت تساوی استفاده کنیم. علامتِ =/
معادلِ مساوی نیست با، و بقیهی علائم هم حتماً میشناسین.
با توجه به نتیجهی بیانیهها، GHCi دو مقدارِ True
یا False
رو برمیگردوند. قبلاً دیدیم که True
و False
ودادهسازهای نوعدادهو ِBool
بودن. اگه تایپِ هر کدوم از این عملگرها رو از GHCiواستعلام کنین، میبینین که تایپِ جوابشون Bool
ِه:
Prelude> :t (==)
(==) :: Eq a => a -> a -> Bool
Prelude> :t (<)
(<) :: Ord a => a -> a -> Bool
به محدودیتهای تایپکلاسی دقت کنین. Eq
تایپکلاسیه که شامل هر چیزِ قابل مقایسه برای تساوی میشه؛ Ord
هم یه تایپکلاسه که شامل هر چیزِ ترتیبدار میشه. و هیچ کدومِشون هم محدود به اعداد نیستن. اعداد رو میشه مقایسه و مرتب کرد، ولی حروف هم همینطور، پس این محدودیتِ تایپکلاس خیلی هم محدودکننده نیست. هر مقداری که بشه براش تساوی یا ترتیب تعریف کرد، میتونه ورودی به این توابعِ تساوی و مقایسه باشه. مابقی اطلاعات تایپ به ما میگه که تابع یکی از این مقادیر رو میگیره، با یه همنوعِ خودش مقایسه میکنه، و یه Bool
برمیگردونه. همونطور که قبلاً هم دیدیم، مقادیرِ Bool
،وTrue
یا False
اند.
یه کم با مقادیر دیگه بازی کنیم:
Prelude> 'a' == 'a'
True
Prelude> 'a' == 'b'
False
Prelude> 'a' < 'b'
True
Prelude> 'a' > 'b'
False
Prelude> 'a' == 'A'
False
Prelude> "Julie" == "Chris"
False
میدونیم که حروف الفبا ترتیب دارن، با این حال معمولاً a رو "کوچکتر" از b نمیگیم. به جاش میگیم که در الفبا a قبل از b میاد. در مثال آخر دیدیم که با نوشته هم همین قاعده کار میکنه. GHCi به درستی تساوی اون دو نوشته رو نقض کرده.
حالا با REPL ببینید 'a'
بزرگتره یا 'A'
.
بعد مثالهای زیر رو بررسی کنید. میتونین دلیل جوابهای REPL رو تشخیص بدین؟
Prelude> "Julie" > "Chris"
True
Prelude> "Chris" > "Julie"
False
خوبه که هسکل هم واقعیت رو میگه! "Julie"
از "Chris"
بزرگتره چون 'J' > 'C'
، اگه دو لغتِ "Back"
و "Brack"
رو مقایسه میکردیم، اون موقع حرف اول رد میشد (چون 'B' == 'B'
) و با مقایسهی حرفهای دوم، "Brack"
بزرگتر میشد ('r' > 'a'
با ترتیب الفبایی). دقت کنید که این مقایسه بر مبنای نمونه ِتایپکلاسِ Ord
برای هر دو تایپِ لیست و Char
انجام شد. فقط لیستهایی رو میشه با هم مقایسه کرد که المانهاشون هم نمونهو ِOrd
داشته باشن. لیستهای زیر قابل مقایسهاند، چون Char
و Integer
هر دو یکی یه نمونه از Ord
دارن:
Prelude> ['a', 'b'] > ['b', 'a']
False
Prelude> 1 > 2
False
Prelude> [1, 2] > [2, 1]
False
نوعداده ای که نمونهو ِOrd
نداره با این توابع کار نمیکنه:
Prelude> data Mood = G | B deriving Show
Prelude> [G, B]
[G, B]
Prelude> [G, B] > [B, G]
<interactive>:28:14:
No instance for (Ord Mood) arising
from a use of ‘>’
In the expression: [G, B] > [B, G]
In an equation for ‘it’:
it = [G, B] > [B, G]
معنی پیغامِ (No instance for (Ord Mood
اینه که نمونه ِOrd
وجود نداره، پس نمیدونه چطور مقادیر رو مرتب کنه.
چیز دیگهای که با این توابع کار نمیکنه:
Prelude> "Julie" == 8
<interactive>:38:12:
No instance for (Num [Char]) arising
from the literal ‘8’
In the second argument of ‘(==)’,
namely ‘8’
In the expression: "Julie" == 8
In an equation for ‘it’:
it = "Julie" == 8
بالاتر گفتیم که توابعِ مقایسه، چندریختی اند و متعاقباً میتونن با تایپهای متنوعی کار کنند. چیز دیگهای که گفتیم این بود که طبق اطلاعات تایپِشون که دیدیم، فقط تایپهای یکسان رو قبول میکردند. به محض اینکه یک مقدارِ String
(در سطح جملهای)، مثل "Julie"
به چنین توابعی میدیم، تایپِ تابع تعیین میشه، و آرگومانِ دوم هم باید از همون تایپ باشه. پیغام خطای بالا میگه که تایپِ مقدارِ لیترالو ِ۸ با تایپِ مقدار اول منطبق نیست، که بر خلافِ انتظارِ این تابعه.