I don’t understand why the following Haskell code terminates under GHCi:
let thereExists f lst = (filter (==True) (map f lst)) /= []
thereExists (\x -> True) [1..]
I did not expect the call to filter to ever complete, given that its second argument is infinite, and I did not think the comparison could take place until the lhs was completely calculated. What’s happening?
The comparison can take place before the LHS is completely calculated. As soon as
filterhas produced one element,/=is able to conclude that the list can’t possibly be equal to[]and immediately returnTrue./=on lists is implemented something like this:Since Haskell is lazy, we will only evaluate the arguments as much as is necessary to choose which right hand side we will use. Evaluation of your example goes something like this:
As soon as we know that the first argument of
/=is(1 : something), it matches the third equation for/=in the code above, so we can returnTrue.However, if you try
thereExists (\x -> False) [1..]it will indeed not terminate, because in that casefilterwill never make any progress towards producing a constructor we can match against.and so on infinitely.
In conclusion,
thereExistson an infinite list can returnTruein finite time, but neverFalse.