Home > other >  Laziness of Haskell and list comprehension. Completion condition
Laziness of Haskell and list comprehension. Completion condition

Time:11-07

foo s1 s2 = null ([x | x <- s2, x == s1])

Please explain when this function will end?

Will Haskell first iterate through the entire list and then check for null, or when one element appears, will he check for null and complete the iteration? If the first option, then how can it be made more lazy?

CodePudding user response:

Will Haskell first iterate through the entire list and then check for null.

No. null checks if it is an empty list, and returns True for an empty list [], and False for the (:) data constructor. The "old" null is implemented as [src]:

null                    :: [a] -> Bool
null []                 =  True
null (_:_)              =  False

It will thus evaluate the list comprehension to head normal form (HNF), and once it knows the outer data constructor it can return True or False: it will not check what the first element is, so if that is an expensive expression, it will not waste time on that one either.

The "new" null is implemented as [src]:

null :: t a -> Bool
null = foldr (\_ _ -> False) True

where foldr for a list is implemented as [src]:

foldr k z = go
          where
            go []     = z
            go (y:ys) = y `k` go ys

which will thus also simply check if the outer data constructor is an empty list [] or a "cons" (:) since in this case k returns True and is not interested in the parameters.

List comprehensions are lazy as well: these will only evaluate the outer data constructor if necessary, and construct the head and tail if necessary. Your list comprehension is desugared to:

concatMap (\x -> if x == s1 then [x] else []) s2

If it thus has to evaluate the outer data constructor of the list, it will iterate over s2, if x == s1 then it will produce as outer data constructor the "cons" and then null can thus use that to determine if the list is empty.

This thus means that from the moment it finds an element x from s2 where x == s1, it will return False.

  • Related