۹ - ۵استفاده از بازه برای ساخت لیست

راه‌های زیادی برای درست کردنِ لیست وجود داره. یکی از ساده‌ترین‌شون استفاده از بازه‌هاست. اساسِ گرامر ِش اینطوریه که یه لیست با المان اولِ لیستِ مورد نظر درست می‌کنین، و بعد از دو تا نقطه، المانِ آخر لیست رو می‌نویسین. در زیر چند مثال از گرامر ِ بازه‌ای، به همراه نسخه‌ی تلخ ِشون (که از توابعِ تایپکلاسِ ‏‎Enum‎‏ استفاده می‌کنن) آوردیم:

Prelude> [1..10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> enumFromTo 1 10
[1,2,3,4,5,6,7,8,9,10]

Prelude> [1,2..10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> enumFromThenTo 1 2 10
[1,2,3,4,5,6,7,8,9,10]

Prelude> [1,3..10]
[1,3,5,7,9]
Prelude> enumFromThenTo 1 3 10
[1,3,5,7,9]

Prelude> [2,4..10]
[2,4,6,8,10]
Prelude> enumFromThenTo 2 4 10
[2,4,6,8,10]

Prelude> ['t'..'z']
"tuvwxyz"

تایپِ توابعی که پشتِ پرده‌ی گرامر ِ بازه‌ای هستن، از این قرارند:

enumFrom       :: Enum a
               => a -> [a]
enumFromThen   :: Enum a
               => a -> a -> [a]

enumFromTo     :: Enum a
               => a -> a -> [a] 
enumFromThenTo :: Enum a
               => a -> a -> a -> [a]

همه‌ی اون توابع، مقادیری که به دنبال بازه‌شون هستیم رو ملزوم به داشتنِ یه نمونه از تایپکلاسِ ‏‎Enum‎‏ می‌کنن. دو تابعِ اول، ‏‎enumFrom‎‏ و ‏‎enumFromThen‎‏، لیست‌هایی با طولِ نامشخص (شاید بینهایت) درست می‌کنن. اگه بخواین یه لیستِ بینهایت درست کنن، باید تایپی رو بدین که در شمارش ِش حدِ بالا نداره. ‏‎Integer‎‏ چنین تایپی‌ه. تا جایی که حافظه باشه، مقادیرِ ‏‎Integer‎‏ رو میشه بزرگ کرد.

حواستون باشه که آرگومانِ اولِ ‏‎enumFromTo‎‏ باید کوچکتر از آرگومانِ دوم‌ش باشه:

Prelude> enumFromTo 3 1
[]
Prelude> enumFromTo 1 3
[1,2,3]

وگرنه یه لیست خالی میده.

تمرین‌ها: ‏‎enumFromTo‎‏

چندتا چیز که لازمه از تایپکلاسِ ‏‎Enum‎‏ بدونین:

Prelude> :info Enum
class Enum a where
  succ :: a -> a
  pred :: a -> a
  toEnum :: Int -> a
  fromEnum :: a -> Int
  enumFrom :: a -> [a]
  enumFromThen :: a -> a -> [a]
  enumFromTo :: a -> a -> [a]
  enumFromThenTo :: a -> a -> a -> [a]
Prelude> succ 0
1
Prelude> succ 1
2
Prelude> succ 'a'
'b'

معادلِ ‏‎enumFromTo‎‏ رو برای تایپ سیگنچرهای داده شده بنویسید. از گرامر ِ بازه‌ای استفاده نکنین. باید همون جوابی رو بده که اگه می‌نوشتین ‏‎[start..stop]‎‏. بجای ‏‎undefined‎‏ (مقداری که با حساب شدن، خطا میده) تعاریف خودتون رو بنویسین.

eftBool :: Bool -> Bool -> [Bool]
eftBool = undefined

eftOrd :: Ordering
       -> Ordering
       -> [Ordering]
eftOrd = undefined

eftInt :: Int -> Int -> [Int]
eftInt = undefined

eftChar :: Char -> Char -> [Char]
eftChar = undefined