Определение степени ленивой оценки - PullRequest
1 голос
/ 10 октября 2011

Учитывая

data BTree a = End
             | Node a (BTree a) (BTree a)
   deriving(Show,Eq,Ord)

data Msg = Msg { from :: String
               , to :: String
               , when :: Int
               , message :: String }

instance Ord Msg where
    compare a b = (when a) `compare` (when b)

instance Eq Msg where
    (==) a b = (when a) == (when b)

Моя функция для подсчета узлов (которая кажется отключенной, но это не вопрос) -

count :: (Ord a) => (BTree a) -> Int
count = sum . count'
 where
  count' :: (Ord a) => (BTree a) -> [Int] 
  count' End = []
  count' (Node _ l r) =
    [1] ++ (count' l) ++ (count' r)

Не count не оценивает содержимое Msg из-за того, что его значение отбрасывается _?Возможно, лучший вопрос в том, как мне узнать, где ленивая оценка начинается и заканчивается для такого рода вещей?

Если третья строка count' была:

count' (Node (Msg x _ _ _) l r) =

Могу ли я предположить,что к другим трем полям Msg было обращено / оценено, или ленивая оценка зашла так далеко?

1 Ответ

1 голос
/ 10 октября 2011

Нет.Поля структуры данных оцениваются лениво по умолчанию.Поскольку вы не используете другие поля в любом случае, они не будут оцениваться этим кодом.Если вы хотите сделать так, чтобы оценка узла заставляла оценивать все его поля, вы можете добавить аннотации строгости к полям:

data BTree a = End
             | Node !a (BTree a) (BTree a)
   deriving(Show,Eq,Ord)

data Msg = Msg { from :: !String
               , to :: !String
               , when :: !Int
               , message :: !String }

Поскольку подсчет узлов вынуждает сами узлы быть оцененными, этотакже заставит оценивать значения узлов.Если вы хотите, чтобы это поведение выполнялось только для одной функции, вы можете выполнить оценку более детально, используя seq:

count' (Node x l r) = x `seq` ([1] ++ count' l ++ count' r)

или шаблон взрыва (требуется расширение BangPatterns)

count' (Node !x l r) = [1] ++ count' l ++ count' r
...