۳ - ۸تمرینهای فصل
خوندنِ گرامر
۱.
سلامت گرامریِ هر کدوم از کُدهای زیر رو تعیین کنین. بعد از اینکه به نتیجه رسیدین، کدها رو توی REPL تست کنین. هر چندتا رو که تونستین تصحیح کنین.
a)
concat [[1, 2, 3], [4, 5, 6]]
b)
++ [1, 2, 3] [4, 5, 6]
c)
(++) "hello" " world"
d)
["hello" ++ "world]
e)
4 !! "hello"
f)
(!!) "hello" 4
g)
take "4 lovely"
h)
take 3 "awesome"
۲.
اینجا دو دسته داریم. دستهی اول چند خط کد اند، و دستهی دوم جواب اونهاست. کد رو بخونین و جوابش رو از دستهی دوم پیدا کنین. حتماً در REPL هم امتحان کنین.
a)
concat [[1 * 6], [2 * 6], [3 * 6]]
b)
"rain" ++ drop 2 "elbow"
c)
10 * head [1, 2, 3]
d)
(take 3 "Julie") ++ (tail "yes")
e)
concat [tail [1, 2, 3],
tail [4, 5, 6],
tail [7, 8, 9]]
جوابِ کدهای بالا رو این زیر نوشتیم، ولی ترتیبشون درست نیست.
a)
"Jules"
b)
[2,3,5,6,8,9]
c)
"rainbow"
d)
[6,12,18]
e)
10
ساخت توابع
۱.
بر مبنای توصیفی که از توابع داده شده، به همراه ورودی و خروجی موردِ نظرشون، تعریف تابع رو بنویسید. اینکار رو مستقیماً در REPL انجام بدین.
به عنوان مثال:
-- اگه تابعتون رو به این مقدار
-- اعمال کنید:
"Hello World"
-- باید چنین جوابی برگردونه:
"ello World"
این جوابِ مناسبیه:
Prelude> drop 1 "Hello World"
"ello World"
حالا بیانیههایی بنویسین که تبدیلاتِ زیر رو انجام بدن. توابعی که تو این فصل دیدین کفایت میکنن و هیچ کدوم نکتهی گمراهکنندهای ندارن.
a)
-- داریم
"Curry is awesome"
-- جواب بده
"Curry is awesome!"
b)
-- داریم
"Curry is awesome!"
-- جواب بده
"y"
c)
-- داریم
"Curry is awesome!"
-- جواب بده
"awesome!"
۲.
حالا جوابهاتون رو به صورت توابعِ جامع که آرگومانهای نوشتاری میگیرن، تو یه فایل بنویسین. از یه متغیر به عنوان آرگومان تابعِ اسمدارِتون استفاده کنین. اگه مطمئن نیستین چطور این توابع رو بنویسین، میتونین تمرینِ waxOff
از فصلِ قبل و یا ماژول ِ TopOrLocal
از این فصل رو دوره کنین.
۳.
یه تابع با تایپِ String -> Char
بنویسین که حرف سومِ ورودیش رو برمیگردونه. یادتون باشه که یه اسم به تابع بدین، و به یه متغیر هم اعمالِش کنین (نه به یه String
ِ معین) تا بشه به String
های مختلف اِعمالِش کرد. مقداری از کد رو اینجا نوشتیم (اگه دوست داشتین اسم تابع رو تغییر بدین. حتماً تایپ سیگنچرِ تابع رو بنویسین؛ تعریف تابع رو هم بعد از علامت مساوی بیارین):
thirdLetter ::
thirdLetter x =
-- اگه اون تابع رو به این مقدار
-- اعمال کنید:
"Curry is awesome"
-- باید این جواب رو برگردونه:
'r'
فقط دقت کنین که مثلِ اکثر زبانهای برنامهنویسی، اندیسها در هسکل از صفر شروع میشن، پس صفرُمین اندیس ِ یه نوشته، حرف اولش میشه. و متعاقباً، سومین اندیس میشه حرف چهارم.
۴.
حالا تابعتون رو طوری تغییر بدین که همیشه با یه نوشته ِ بهخصوص کار کنه، و اندیس ِ حرف مورد نظر رو به عنوان ورودی بگیره (میتونین از Curry is awesome! برای نوشته ِ داخلِ تابع استفاده کنین، یا اگه دوست داشتین یه نوشته ِ دیگه بنویسین).
letterIndex :: Int -> Char
letterIndex x =
۵.
با استفاده از توابعِ take
و drop
که تو این فصل دیدیم، سعی کنین یه تابع به اسم rvrs
بنویسین (خلاصهای از لغت reverse به معنای معکوس. Prelude
خودِش یه تابع به اسم reverse
داره و اگه شما هم همون اسم رو به تابعتون بدین، پیغام خطا میگیرین) که نوشتهی Curry is awesome رو به نوشتهی awesome is Curry تبدیل میکنه. کُد خیلی جالبی نیست، اما چیزهایی که تا الان یاد گرفتیم برای نوشتنِ این تابع کاملاً کفایت میکنن. اول تابع رو تو یه فایل تعریف کنین. قرار نیست که این تابع لغات همهی جملات رو معکوس کنه، فقط با drop
و take
لغاتِ همون یک جمله رو جابجا کنین.
۶.
حالا سعی کنیم فایلمون رو به یه ماژول گسترش بدیم. این کار اجازه میده بعداً توابع بیشتری بهش اضافه کنیم، همچنین میتونیم توابعِ این ماژول رو به ماژولهای دیگه صادر کنیم تا اونها هم به این توابع دسترسی پیدا کنن. راههای متفاوتی برای این کار هست، ولی برای راحتی؛ این الگوی ساده رو در زیر آوردیم:
module Reverse where
rvrs :: String -> String
rvrs x =
main :: IO ()
main = print ()
داخل پرانتز جلوی print
، تابع rvrs
رو با آرگومانی که میخواین بهش اعمال شه (در این مورد Curry is awesome) بنویسین. حالا اون تابع rvrs
به همراه آرگومانِش، مجموعاً آرگومان تابع print
شدن. دقت کنید که حتماً داخل پرانتز بنویسین، تا نتیجهی rvrs
چاپ بشه.
البته همونطور که گفتیم، میشه از $
هم برای کاهش پرانتزها استفاده کرد. این روش هم امتحان کنین.