[Haskell-cafe] how to print out intermediate results in a recursive function?

Qi Qi qiqi789 at gmail.com
Sun Feb 5 08:17:31 CET 2012


Brilliant! That's what I was looking for. Thanks for all the replies.

Sometimes, I suspect that Haskell not only makes easier of the hard things for
imperative programming languages but also makes harder of some easy things. 

Roman Cheplyaka <roma at ro-che.info> writes:

> * Steve Horne <sh006d3592 at blueyonder.co.uk> [2012-02-04 11:54:44+0000]
>> On 04/02/2012 08:46, MigMit wrote:
>> >Well, if you want that in production, not for debugging purposes, you should change the type signature of mergesort so that it uses some monad. Printing requires IO monad; however, I would advise to collect all intermediate results using Writer monad, and print them afterwards:
>> >
>> >mergesort [] = return []
>> >mergesort [x] = return [x]
>> >mergesort xs = do
>> >   tell [xs] -- that's right, "[xs]", not "xs"
>> >   let (as, bs) = splitAt (length xs `quot` 2) xs
>> >   liftM2 merge (mergesort as) (mergesort bs)
>> Also, don't forget that IO actions are values too. IOW, your list of
>> intermediate results can be a list of IO actions, effectively
>> deferring their "execution" until later.
>
> No need to keep them in a list -- you can compose them as you go, while
> still deferring the execution.
>
> import Data.Monoid
> import Control.Monad.Writer
>
> newtype O = O (IO ())
>
> instance Monoid O where 
>     mempty = O $ return ()
>     mappend (O a) (O b) = O $ a >> b
>
> mergesort [] = return []
> mergesort [x] = return [x]
> mergesort xs = do
>     trace xs 
>     let (as, bs) = splitAt (length xs `quot` 2) xs
>     liftM2 merge (mergesort as) (mergesort bs)
>       where
>         trace = tell . O . print
>
> main =
>     let (_, O trace) = runWriter $ mergesort [3,1,4,2,10,8,4,7,6]
>     in trace

-- 
Qi Qi



More information about the Haskell-Cafe mailing list