确定懒惰评估的程度

时间:2011-10-10 16:38:06

标签: haskell lazy-evaluation binary-search-tree

鉴于

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 个答案:

答案 0 :(得分:1)

没有。默认情况下,数据结构的字段会被懒惰地评估。由于您没有以任何方式使用其他字段,因此此代码不会对它们进行评估。如果要使其评估节点强制评估其所有字段,可以在字段中添加严格注释:

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