۱۰ - ۱۰تمرینهای فصل
نرمش و دوره
برای این تمرینها انتظار نمیره از فولد استفاده کنین. اینها رو برای دورهی مطالبی که در فصلهای قبل خوندیم آوردیم. با هر راهی که تا اینجا یاد گرفتین حل کنین.
۱.
با حروفِ بیصدا و صدادارِ زیر:
stops = "pbtdkg"
vowels = "aeiou"a)
تابعی بنویسین که stops و vowels رو به عنوان ورودی بگیره، و همهی توپلهای سهتاییِ ممکن با ترکیبِ ساکن-صدادار-ساکن رو برگردونه. همهی توپلها یه لغت انگلیسی نمیشن، ولی این ساکن-صدادار-ساکن انقدر رایجه که خیلیهاشون یه لغاتِ معنیداری میشن.
b)
تابع بالا رو تغییر بدین تا فقط توپلهایی رو بده که با p شروع میشن.
c)
حالا بجای لیستِ حروف ساکن و صدادار، لیستهایی از اسم و فعل تعریف کنین، و کاری کنین تابعتون توپلهای اسم-فعل-اسم برگردونه.
۲.
تابعِ رمزآلود زیر چی کار میکنه؟ تایپش چیه؟ سعی کنین قبل از تست کردن تو REPL، مطمئن بشین چه کاری انجام میده.
seekretFunc x =
div (sum (map length (words x)))
(length (words x))۳.
جواب دقیقتر میخوایم... میتونین تابعِ بالا رو با تقسیمِ کسری بازنویسی کنین؟
بازنویسی توابع با فولد
در فصلِ قبل این توابع رو با خوداتکایی روی لیست نوشتین. حالا برای این تمرین با فولد بازنویسیشون کنین. برای درک بهتر فولدها، هرجا میشد، نسخهی فولددار رو بینقطه بازنویسی کنین.
نسخهی بینقطه ِ این توابع که با فولد تعریف شدن، شبیهِ این میشه:
myFunc = foldr f zبرای مثال، تابعِ and:
-- باز هم با این تایپ کاربردشون
-- محدودتر از نسخهی معادلشون در
-- .یا جدیدتر میشه. مهم نیست GHC 7.10
-- (&&) مستقیم، بدون recursion
myAnd :: [Bool] -> Bool
myAnd [] = True
myAnd (x:xs) =
if x == False
then False
else myAnd xs
-- (&&) مستقیم، با استفاده از recursion
myAnd :: [Bool] -> Bool
myAnd [] = True
myAnd (x:xs) = x && myAnd xs
-- تعریف با فولد،
-- تابع فولدینگ بینقطه نیست
myAnd :: [Bool] -> Bool
myAnd = foldr
(\a b ->
if a == False
then False
else b) True
-- myAnd تعریف با فولد، حالا هم
-- و هم تابع فولدینگ بینقطهاند
myAnd :: [Bool] -> Bool
myAnd = foldr (&&) Trueهدفْ رسیدن به آخرین نسخهست؛ هرجا که ممکن بود. لازم نیست هر چهار نسخهی بالا رو برای تمرینها بنویسین، ولی هر چقدر نسخههای بیشتری بنویسین، درک بهتری از توابعشون پیدا میکنین.
۱.
تابعِ myOr اگه حداقل یک مقدارِ Bool در لیستِ ورودی True باشه، باید True برگردونه.
myOr :: [Bool] -> Bool
myOr = undefined۲.
تابعِ myAny در صورتی True بر میگردونه که از اعمال ِ a -> Bool به حداقل یکی از المانهای لیست، جوابِ True بدست بیاد.
myAny :: (a -> Bool) -> [a] -> Bool
myAny = undefinedچندتا مثال برای تست کردنِ myAny:
Prelude> myAny even [1, 3, 5]
False
Prelude> myAny odd [1, 3, 5]
True۳.
دو نسخه از تابعِ myElem تعریف کنین: یکی با فولد کار کنه، و اون یکی با any.
myElem :: Eq a => a -> [a] -> Bool Prelude> myElem 1 [1..10]
True
Prelude> myElem 1 [2..10]
False۴.
تابعِ myReverse رو تعریف کنین. نگرانِ تنبل کردنِش نباشین.
myReverse :: [a] -> [a]
myReverse = undefinedPrelude> myReverse "blah"
"halb"
Prelude> myReverse [1..5]
[5,4,3,2,1]۵.
تابعِ myMap رو با foldr تعریف کنین. باید مثلِ خودِ map عمل کنه.
myMap :: (a -> b) -> [a] -> [b]
myMap = undefined۶.
تابعِ myFilter رو با foldr تعریف کنین. باید مثل خود filter عمل کنه.
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter = undefined۷.
تابعِ squish یه لیستِ لیست رو به یک لیست تبدیل میکنه.
squish :: [[a]] -> [a]
squish = undefined۸.
تابعِ squishMap یه تابع رو به یک لیست نگاشت میده و نتیجههاشون رو الحاق میکنه.
squishMap :: (a -> [b]) -> [a] -> [b]
squishMap = undefinedλ> squishMap (\x -> [1, x, 3]) [2]
λ> [1,2,3]
λ> squishMap (\x -> "WO "++[x]++" OT ") "blah"
"WO b OT WO l OT WO a OT WO h OT "۹.
تابعِ squishAgain یه لیستِ لیست رو به یک لیست لِه میکنه. این بار از تابعِ squishMap استفاده کنین.
squishAgain :: [[a]] -> [a]
squishAgain = undefined۱۰.
تابعِ myMaximumBy یک تابعِ مقایسه و یک لیست میگیره، و بر مبنای آخرین مقداری که از مقایسه خروجیِ GT میده، بزرگترین المانِ لیست رو برمیگردونه.
myMaximumBy :: (a -> a -> Ordering)
-> [a]
-> a
myMaximumBy = undefinedPrelude> myMaximumBy (\_ _ -> GT) [1..10]
1
Prelude> myMaximumBy (_ _ -> LT) [1..10]
10
Prelude> myMaximumBy compare [1..10]
10۱۱.
تابعِ myMinimumBy یک تابع مقایسه و یک لیست میگیره، و بر مبنای آخرین مقداری که از مقایسه خروجیِ LT میده، کوچکترین المانِ لیست رو برمیگردونه.
myMinimumBy :: (a -> a -> Ordering)
-> [a]
-> a
myMinimumBy = undefinedPrelude> myMinimumBy (\_ _ -> GT) [1..10]
10
Prelude> myMinimumBy (_ _ -> LT) [1..10]
1
Prelude> myMinimumBy compare [1..10]
1