۲۶ - ۱۳اضافهکردنِ اکیدی
حالا با اضافه کردنِ اکیدی به تایپِ List و چندتا از عملیاتهاش، تغییرِ رفتارش در حضورِ تهی رو بررسی میکنیم. این بخش بیشتر به منظورِ نمایش نوشته شده تا به عنوان یه مثالِ عملی.
module StrictTest1 where
data List a =
Nil
| Const a (List a) deriving Show
sTake :: Int -> List a -> List a
sTake n _
| n <= 0 = Nil
sTake n Nil = Nil
sTake n (Cons x xs) =
(Cons x (sTake (n-1) xs))
twoEls = Cons 1 (Cons undefined Nil)
oneEl = sTake 1 twoElsاسمِ این ماژول خیلی دقیق نیست... اینجا List، درست مثلِ [a]، تعریف شده در Prelude ِ هسکل، تنبل ِه. تابعِ take ِ اختصاصیِ خودمون (که اسمش رو sTake گذاشتیم) هم تنبل ِه.
بیاریمش تو REPL ببینیم:
Prelude> twoEls
Cons 1 (Cons *** Exception: Prelude.undefined
Prelude> oneEl
Cons 1 Nilحالا ببینیم با اضافه کردنِ اکیدی در جاهای مختلفِ برنامهمون، رفتارش چطور تغییر میکنه.
اول BangPatterns رو اضافه میکنیم تا راحتتر بتونیم جاهایی که اکیدی میخوایم رو تعیین کنیم:
{-# LANGUAGE BangPatterns #-}
module StrictTest2 where
data List a =
Nil
| Const !a (List a) deriving Show
sTake :: Int -> List a -> List a
sTake n _
| n <= 0 = Nil
sTake n Nil = Nil
sTake n (Cons x xs) =
(Cons x (sTake (n-1) xs))
twoEls = Cons 1 (Cons undefined Nil)
oneEl = sTake 1 twoElsاون علامت تعجب رو دیدین؟ خوب توی REPL بارگذاریش کنیم:
Prelude> twoEls
Cons 1 *** Exception: Prelude.undefined
Prelude> oneEl
Cons 1 Nilیه کم اکیدتر:
{-# LANGUAGE BangPatterns #-}
module StrictTest3 where
data List a =
Nil
| Const !a (List a) deriving Show
sTake :: Int -> List a -> List a
sTake n _
| n <= 0 = Nil
sTake n Nil = Nil
sTake n (Cons x !xs) =
(Cons x (sTake (n-1) xs))
twoEls = Cons 1 (Cons undefined Nil)
oneEl = sTake 1 twoEls
threeElements = Cons 2 twoEls
oneElT = sTake 1 threeElementsبه xs اکیدی اضافه کردیم تا sTake مابقی لیست رو اجبار کنه:
Prelude> twoEls
Cons 1 *** Exception: Prelude.undefined
Prelude> oneEl
*** Exception: Prelude.undefined
Prelude> threeElements
Cons 2 (Cons 1 *** Exception: Prelude.undefined
Prelude> oneElT
Cons 2 Nilباز هم اکیدتر:
module StrictTest4 where
data List a =
Nil
| Const !a !(List a) deriving Show
sTake :: Int -> List a -> List a
sTake n _
| n <= 0 = Nil
sTake n Nil = Nil
sTake n (Cons x xs) = (Cons x (sTake (n-1) xs))
twoEls = Cons 1 (Cons undefined Nil)
oneEl = sTake 1 twoEls
Prelude> twoEls
*** Exception: Prelude.undefined
Prelude> oneEl
*** Exception: Prelude.undefinedپس از این آزمایشها چه نتیجهای میگیریم؟
| N | Cons | sTake |
|---|---|---|
| ۱ | Cons a (List a) | Cons x xs |
| ۲ | Cons !a (List a) | Cons x xs |
| ۳ | Cons !a (List a) | Cons x !xs |
| ۴ | Cons !a !(List a) | Cons x xs |
اینها آزمایشها بودن. حالا خودِ نتایج:
| N | twoEls | oneEl |
|---|---|---|
| ۱ | Cons 1 (Cons *** | Cons 1 Nil |
| ۲ | Cons 1 *** | Cons 1 Nil |
| ۳ | Cons 1 *** | *** |
| ۴ | *** | *** |
تأثیرِ اضافه کردنِ اکیدی در جاهای مختلف روی محاسبات، نسبت به تهی کاملاً مشخصه.