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

Roman Cheplyaka roma at ro-che.info
Sat Feb 4 14:52:11 CET 2012


* 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

-- 
Roman I. Cheplyaka :: http://ro-che.info/



More information about the Haskell-Cafe mailing list