darcs patch: Improve Control.Monad.filterM:

Simon Marlow simonmarhaskell at gmail.com
Tue Aug 8 11:24:33 EDT 2006


Chris Kuklewicz wrote:
> Simon Marlow wrote:
> 
>> Spencer Janssen wrote:
>>
>>> Fri Aug  4 13:49:57 CDT 2006  Spencer Janssen <sjanssen at cse.unl.edu>
>>>   * Improve Control.Monad.filterM:
>>>    * filterM is defined in terms of foldr, making it a good consumer 
>>> in GHC's      fusion framework
>>>    * filterM uses linear stack space with respect to the number of 
>>> items that      the predicate returns true, rather than the total 
>>> number of elements in      the input.
>>
>> ...
>>
>>> hunk ./Control/Monad.hs 151
>>> -filterM _ []     =  return []
>>> -filterM p (x:xs) =  do
>>> -   flg <- p x
>>> -   ys  <- filterM p xs
>>> -   return (if flg then x:ys else ys)
>>> +filterM p        = foldr f (return [])
>>> + where +    f x xs = do
>>> +                flg <- p x
>>> +                if flg
>>> +                    then xs >>= return . (x:)
>>> +                    else xs
>>> }
>>
>>
>> The new definition looks less lazy than the original, so it's not a 
>> drop-in
>> replacement.  Also, we would need some measurements to test whether 
>> this version
>> doesn't lose efficiency - it probably fuses better, but might be 
>> slower when it
>> doesn't fuse.  Rules to turn the foldr version back into the recursive 
>> version
>> might be needed (or aggressive inlining).
>>
> 
> The new one looks better to me.

It may well be better, but it doesn't have the same laziness properties, so it 
isn't the same function.  eg. try this:

  do filterM (\x -> return undefined) [1]; return ()

Of course we may discuss whether the extra laziness is useful, but I can't apply 
the patch as it stands because it would break Haskell 98.

 > But the foldr is not needed:

The foldr was there to allow fusion, I believe.

Cheers,
	Simon


More information about the Libraries mailing list