۴ - ۵مقایسه‌ی مقادیر

تا اینجا بیشترِ عملیاتی که با اعداد داشتیم محاسبات بودن. اعداد رو میشه برای تساوی، بزرگتر بودن، یا کوچکتر بودن هم مقایسه کرد:

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" به چنین توابعی میدیم، تایپِ تابع تعیین میشه، و آرگومانِ دوم هم باید از همون تایپ باشه. پیغام خطای بالا میگه که تایپِ مقدارِ لیترال ِ۸ با تایپِ مقدار اول منطبق نیست، که بر خلافِ انتظارِ این تابع‌ه.