۶ - ۱۴تمرین‌های فصل

تستی

۱.

کلاس ‏‎Eq‎‏

a)

شامل همه‌ی تایپ‌ها در هسکل میشه

b)

با تایپکلاس ‏‎Ord‎‏ یکسانه

c)

بررسی تساوی رو ممکن می‌کنه

d)

فقط شامل تایپ‌های عددی میشه

۲.

تایپکلاس ‏‎Ord‎‏

a)

امکان مقایسه‌ی همه‌ی مقادیر با هم رو میده

b)

یه زیرکلاس از ‏‎Eq‎‏ ِه

c)

یه سوپرکلاس برای ‏‎Eq‎‏ ِه

d)

هیچ نمونه‌ای برای ‏‎Bool‎‏ نداره

۳.

فرض کنیم تایپکلاس ‏‎Ord‎‏ یه عملگر ِ ‏‎>‎‏ داره. تایپ‌ش چیه؟

a)

‏‎Ord a => a -> a -> Bool‎‏

b)

‏‎Ord a => Int -> Bool‎‏

c)

‏‎Ord a => a -> Char‎‏

d)

‏‎Ord a => Char -> [Char]‎‏

۴.

در بیانیه‌ی ‏‎x = divMod 16 12‎‏

a)

‏‎x‎‏ تایپ‌ش ‏‎Integer‎‏ ِه

b)

مقدار ‏‎x‎‏ رو نمیشه تشخیص داد

c)

تایپِ ‏‎x‎‏ توپل ِه

d)

‏‎x‎‏ برابرِ ‏‎12 / 16‎‏ میشه

۵.

تایپکلاس ‏‎Integral‎‏ شامل

a)

اعداد ‏‎Int‎‏ و ‏‎Integer‎‏

b)

اعداد ‏‎Integral‎‏، ‏‎Real‎‏، و ‏‎Fractional‎‏

c)

گربه‌ی شرودینگر

d)

فقط اعداد مثبت

تایپچک میشه؟

تو این بخش از تمرین‌ها، دنبالِ خطاهای تایپ و تایپکلاس گشتن رو تمرین می‌کنین.

برای مثال ‏‎printIt‎‏ کار نمی‌کنه چون تابع‌هایی مثلِ ‏‎x‎‏ هیچ نمونه‌ای از ‏‎Show‎‏ ندارن – تایپکلاسی که اجازه‌ی تبدیلِ چیزها به نوشته رو میده (معمولاً برای چاپ):

x     :: Int -> Int
x blah = blah + 20

printIt :: IO ()
printIt = putStrLn (show x)

این خطاییه که بعد از بارگذاری می‌گیرین:

No instance for (Show (Int -> Int)) arising
  from a use of ‘show’

In the first argument of ‘putStrLn’,
  namely ‘(show x)’
In the expression: putStrLn (show x)
In an equation for ‘printIt’:
  printIt = putStrLn (show x)

پیغام میگه نمونه ِ ‏‎Show‎‏ برای تایپ ‏‎Int -> Int‎‏ پیدا نکرده، که با عقل جور در میاد. در هسکل به طور پیش‌فرض هیچ چیز با نوع‌ساز ِ تابع ‏‎(->)‎‏ نمی‌تونه نمونه ِ ‏‎Show‎‏ داشته باشه.

کدهای زیر رو بررسی کنین و بگین تایپچک میشن یا نه، بعد هم با GHC تست کنین. اگه تایپچک نمیشه، سعی کنین پیغام خطا رو با حدسِ خودتون از ایرادِ کُد مقایسه کنین. اگر هم تونستین کد رو درست کنین.

۱.

کد زیر تایپچک میشه؟ اگه نه، چرا؟

data Person = Person Bool

printPerson :: Person -> IO ()
printPerson person = putStrLn (show person)

۲.

کد زیر تایپچک میشه؟ اگه نه، چرا؟

data Mood = Blah
          | Woot deriving Show 

settleDown x = if x == Woot
               then Blah
               else x

۳.

اگه کاری کنین ‏‎settleDown‎‏ تایپچک بشه، اون موقع:

a)

چه مقادیری برای ورودیِ تابع قابل قبول‌اند؟

b)

چی میشه اگه ‏‎settleDown 9‎‏ رو اجرا کنین؟ چرا؟

c)

اگه ‏‎Blah > Woot‎‏ رو اجرا کنین چی میشه؟ چرا؟

۴.

کد زیر تایپچک میشه؟ اگه نه، چرا؟

type Subject = String
type Verb = String
type Object = String

data Sentence =
  Sentence Subject Verb Object
  deriving (Eq, Show)

s1 = Sentence "dogs" "drool"
s2 = Sentence "Julie" "loves" "dogs"

با یه تعریفِ نوع‌داده، چی کار میشه کرد؟

با تعاریف نوع‌داده‌های زیر:

data Rocks =
  Rocks String deriving (Eq, Show)

ata Yeah =
  Yeah Bool deriving (Eq, Show)

ata Papu =
  Papu Rocks Yeah
  deriving (Eq, Show)

کدوم کدهای زیر تایپچک میشن؟ اونهایی که نمیشن مشکل‌شون چیه؟

۱.

phew = Papu "chases" True

۲.

truth = Papu (Rocks "chomskydoz")
             (Yeah True)

۳.

equalityForAll :: Papu -> Papu -> Bool
equalityForAll p p' = p == p'

۴.

comparePapus :: Papu -> Papu -> Bool
comparePapus p p' = p > p'

تایپ‌ها رو جور کنین

یه بیانیه با دو تا تایپ بهتون می‌دیم، و شما باید بگین که آیا میشه تایپِ دوم رو با تایپِ اول عوض کرد یا نه. برای تست، می‌تونین همه‌ی بیانیه‌ها رو با تایپِ اول‌شون تو یه فایل بنویسین و بعد تایپ‌ها رو با تایپِ دوم عوض کنین، بارگذاری کنین و ببینین کار می‌کنه یا نه. حدس نزنین، همه‌ی جواب‌هاتون رو چک کنین!

۱.

برای تعریفِ زیر:

a)

i :: Num a => a
i = 1

b)

حالا با این تایپ سیگنچر امتحان کنین:

i :: a

اول به جواب خودتون برسین و بعد تست‌ش کنین. وقتی درست یا غلط بودنِ جواب‌تون رو درک کردین، با GHCi امتحان کنین ببینین بدون اینکه تایپی تعریف کنین، چه تایپی برای بیانیه نتیجه می‌گیره. مثلاً برای این مثال، بنویسین:

Prelude> let i = 1
Prelude> :t i
--جواب رو عمداً نیاوردیم. 

۲.

a)

f :: Float
f = 1.0

b)

f :: Num a => a

۳.

a)

f :: Float
f = 1.0

b)

f :: Fractional a => a

۴.

راهنمایی: ‏‎:info RealFrac‎‏ رو در REPL تایپ کنین.

a)

f :: Float
f = 1.0

b)

f :: RealFrac a => a

۵.

a)

freud :: a -> a
freud x = x

b)

freud :: Ord a => a -> a

۶.

a)

freud' :: a -> a
freud' x = x

b)

freud' :: Int -> Int

۷.

a)

myX = 1 :: Int
sigmund :: Int -> Int
sigmund x = myX

b)

sigmund :: a -> a

۸.

a)

myX = 1 :: Int
sigmund' :: Int -> Int
sigmund' x = myX

b)

sigmund' :: Num a => a -> a

۹.

باید ‏‎sort‎‏ رو از ‏‎Data.List‎‏ وارد کنین.

a)

jung :: Ord a => [a] -> a
jung xs = head (sort xs)

b)

jung :: [Int] -> Int

۱۰.

a)

young :: [Char] -> Char
young xs = head (sort xs)

b)

young :: Ord a => [a] -> a

۱۱.

a)

mySort :: [Char] -> [Char]
mySort = sort
signifier :: [Char] -> Char
signifier xs = head (mySort xs)

b)

signifier :: Ord a => [a] -> a

تایپ-وان-دو ۲

راندِ دوم! مثل قبل – باید جاهای خالی رو طوری پر کنید که با تایپ‌ها جور بشن. هدفِ این تمرین‌ها اینه که شما تعریفِ یه بیانیه رو از روی تایپ‌ش پیدا کنین. احتمالاً چندتا چیز از ‏‎Prelude‎‏ لازم بشه.

۱.

chk :: Eq b => (a -> b) -> a -> b -> Bool
chk = ???

۲.

-- با یکی از عملیات حساب، مقادیرِ 
-- رو ترکیب کنین Integer و b
arith :: Num b
      => (a -> b)
      -> Integer
      -> a
      -> b
arith = ???