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

دوره‌ی تایپ‌ها

۱.

تایپِ این چیه؟

[[True, False], [True, True], [False, True]]

a)

‏‎Bool‎‏

b)

اکثراً ‏‎True‎‏

c)

‏‎[a]‎‏

d)

‏‎[[Bool]]‎‏

۲.

کدوم یکی از داده‌‌های زیر، تایپ یکسانی با این دارن؟

[[True, False], [True, True], [False, True]]

a)

‏‎[(True, False), (True, True), (False, True)]‎‏

b)

‏‎[[3 == 3], [6 > 5], [3 < 4]]‎‏

c)

‏‎[3 == 3, 6 > 5, 3 < 4]‎‏

d)

‏‎["Bool", "more Bool", "Booly Bool!"]‎‏

۳.

برای تابع زیر، کدوم گزینه حقیقت داره؟

func    :: [a] -> [a] -> [a]
func x y = x ++ y

a)

‏‎x‎‏ و ‏‎y‎‏ باید از یه تایپ باشن

b)

‏‎x‎‏ و ‏‎y‎‏ باید هر دو لیست باشن

c)

اگه ‏‎x‎‏ یه ‏‎String‎‏ باشه، ‏‎y‎‏ هم باید ‏‎String‎‏ باشه

d)

هر سه مورد

۴.

کدوم یکی از گزینه‌های زیر، یه اعمال ِ درست از ‏‎func‎‏ به هر دو آرگومان‌هاشه؟

a)

‏‎func "Hello World"‎‏

b)

‏‎func "Hello" "World"‎‏

c)

‏‎func [1, 2, 3] "a, b, c"‎‏

d)

‏‎func ["Hello", "World"]‎‏

دوره‌ی کاری کردن

با تعاریفِ زیر، بگین اعمال‌های اونها چه نتیجه‌هایی میدن. طبق معمول، اول جواب‌ها رو پیدا کنین، بعد در REPL تست کنین.

cattyConny :: String -> String -> String
cattyConny x y = x ++ " mrow " ++ y

-- تایپ‌ها رو بنویسین

flippy = flip cattyConny

appedCatty = cattyConny "woops"
frappe = flippy "haha"

۱.

appedCatty "woohoo!"

۲.

frappe "1"

۳.

frappe (appedCatty "2")

۴.

appedCatty (frappe "blue")

۵.

cattyConny
  (frappe "pink")
  (cattyConny "green" (appedCatty "blue"))

۶.

cattyConny (flippy "Pugs" "are") "awesome"

خوداتکایی

۱.

مراحل ساده شدنِ ‏‎dividedBy 15 2‎‏ تا جواب آخر رو بنویسین.

۲.

تابعی بنویسین که به صورتِ بازگشتی، همه‌ی اعداد از ۱ تا n رو جمع کنه (n آرگومان تابع). مثلاً اگه n عدد ۵ باشه، جمع ۵+۴+۳+۲+۱ رو حساب می‌کنه و جواب ۱۵ میده. تایپ‌ش باید ‏‎(Eq a, Num a) => a -> a‎‏ باشه.

۳.

تابعی بنویسین که دو عددِ صحیح رو با جمعِ بازگشتی ضرب کنه. تایپ‌ش باید ‏‎(Integral a) => a -> a -> a‎‏ باشه.

تعمیرِ ‏‎dividedBy‎‏

تابع ‏‎dividedBy‎‏ که تعریف کردیم ایده‌آل نبود. یکی از دلایل‌ش هم ناقص بودنِ تابع بود، با مقسوم‌علیه ِ صفر یا کوچکتر جوابی نمیداد (تهی).

با استفاده از تابعِ ‏‎div‎‏ که از قبل تعریف شده، جواب تابع با اعداد منفی رو میشه دید:

Prelude> div 10 2
5
Prelud> div 10 (-2)
-5
Prelude> div (-10) (-2)
5
Prelude> div (-10) (2)
-5

مشکل بعدی، تقسیم با مخرج صِفره. در ریاضی، تقسیم بر صفر جوابی نداره، ما هم باید از نوع‌داده ای استفاده کنیم که بشه به کمک‌ش بی‌جواب بودنِ تقسیم به صفر رو بیان کنیم. اگه راهنمایی لازم دارین، نوع‌داده ِ زیر شاید شروع خوبی باشه.

data DividedResult =
    Result Integer
  | DividedByZero

تابعِ مَک‌کارتی ۹۱

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

تابع مَک‌کارتی ۹۱ با ‏‎x > ۱۰۰‎‏ جوابِ ‏‎x - ۱۰‎‏، و در غیر اینصورت جوابِ ۹۱ میده. یه تابعِ بازگشتی ِه.

        ⎧ n - 10,         n > 100
MC(n) = ⎨
        ⎩ MC(MC(n + 11)), n ≤ 100
mc91 = undefined

هنوز ‏‎map‎‏ رو توضیح ندادیم، فعلاً کافیه بدونین که یه تابع رو به تک‌تک اعضای یه لیست اعمال می‌کنه و لیست حاصل رو برمی‌گردونه. در فصل بعد بیشتر توضیح میدیم.

Prelude> map mc91 [95..110]
[91,91,91,91,91,91,91,92,93,94,95,96,97,98,99,100]

اعداد به لغات

module WordNumber where

import Data.List (intersperse)

digitToWord :: Int -> String
digitToWord n = undefined

digits :: Int -> [Int]
digits n = undefined

wordNumber :: Int -> String
wordNumber n = undefined

بجای ‏‎undefined‎‏ تعریف توابع رو بنویسین. ‏‎n‎‏ بعد از اسم توابع آرگومان با تایپِ ‏‎Int‎‏ ِه.

توابع رو طوری تعریف کنین تا ‏‎wordNumber‎‏ لغت انگلیسی معادل هر مقدارِ ‏‎‎‏Int رو برگردونه. اول یه تابع می‌نویسین که اعداد از صفر تا ۹ رو به معادلِ انگلیسی‌شون تبدیل می‌کنه (‏‎one‎‏، ‏‎two‎‏، الی آخر). بعد هم یه تابع تعریف می‌کنین که ارقام عدد ورودی رو جدا می‌کنه و یه لیستِ ‏‎Int‎‏ برمی‌گردونه. در انتها هم باید تابع اول رو به لیست اعداد (از تابع دوم) اعمال کنین و به یک نوشته که اسمِِ اعداد با خط فاصله از هم جدا شدن تبدیل کنین.

برای حل این مسئله، چندتا تابع که ممکنه لازم بشن رو اینجا نوشتیم. بسته به اینکه چطور تابع رو بنویسین، ممکنه همه‌شون لازم‌تون نشن – فقط برای پیشنهاد نوشتیم. باهاشون بازی کنین و اطلاعات‌شون رو نگاه کنین تا بهتر بشناسین‌شون.

ممکنه این تمرین به نظرتون سخت بیاد.

div         :: Integral a => a -> a -> a
mod         :: Integral a => a -> a -> a
map         :: (a -> b) -> [a] -> [b]
concat      :: [[a]] -> [a] 
intersperse :: a -> [a] -> [a]
(++)        :: [a] -> [a] -> [a] 
(:[])       :: a -> [a]

اینها رو هم در نظر داشته باشین:

Prelude> div 135 10
13
Prelude> mod 135 10
5
Prelude> div 13 10
1
Prelude> mod 13 10
3

تابع‌تون باید چنین جواب‌هایی بده:

Prelude> wordNumber 12324546
"one-two-three-two-four-five-four-six"
Prelude>