how to print out intermediate results in a recursive function?

Hello, I have a question;how can I print out the intermediate number lists in a mergesort recursive function like the following one. merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys mergesort [] = [] mergesort [x] = [x] mergesort xs = let (as, bs) = splitAt (length xs `quot` 2) xs in merge (mergesort as) (mergesort bs) main = do print $ mergesort [5,4,3,2,1] In the main function, it only prints out the final number list. But I'd like to print out the number lists in every recursive level. How can I do that? Thanks. -- Qi Qi

On 5 February 2012 05:23, Qi Qi
Hello,
I have a question;how can I print out the intermediate number lists in a mergesort recursive function like the following one.
You can use the (completely evil and shouldn't be used in production code) Debug.Trace module.
merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
mergesort [] = [] mergesort [x] = [x] mergesort xs = let (as, bs) = splitAt (length xs `quot` 2) xs in merge (mergesort as) (mergesort bs)
main = do print $ mergesort [5,4,3,2,1]
In the main function, it only prints out the final number list. But I'd like to print out the number lists in every recursive level. How can I do that? Thanks.
-- Qi Qi
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

You can use trace from Debug.Trace, change the code like this:
mergesort l = case trace l l of
[] -> ...
[x] -> ...
(x:xs) -> ...
On Sun, Feb 5, 2012 at 2:23 AM, Qi Qi
Hello,
I have a question;how can I print out the intermediate number lists in a mergesort recursive function like the following one.
merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
mergesort [] = [] mergesort [x] = [x] mergesort xs = let (as, bs) = splitAt (length xs `quot` 2) xs in merge (mergesort as) (mergesort bs)
main = do print $ mergesort [5,4,3,2,1]
In the main function, it only prints out the final number list. But I'd like to print out the number lists in every recursive level. How can I do that? Thanks.
-- Qi Qi
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi, There is also this nice trick to use Debug.Trace: merge xs ys | trace (show (xs,ys)) False = undefined -- add this as the first case to merge mergesort xs | trace (show xs) False = undefined -- and this as the first case to mergesort HTH, Ozgur

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) On 4 Feb 2012, at 22:23, Qi Qi wrote:
Hello,
I have a question;how can I print out the intermediate number lists in a mergesort recursive function like the following one.
merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
mergesort [] = [] mergesort [x] = [x] mergesort xs = let (as, bs) = splitAt (length xs `quot` 2) xs in merge (mergesort as) (mergesort bs)
main = do print $ mergesort [5,4,3,2,1]
In the main function, it only prints out the final number list. But I'd like to print out the number lists in every recursive level. How can I do that? Thanks.
-- Qi Qi
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

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
On 04/02/2012 08:46, MigMit wrote: their "execution" until later.

* Steve Horne
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/

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
* Steve Horne
[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

On Sun, Feb 05, 2012 at 01:17:31AM -0600, Qi Qi wrote:
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.
This is true. But usually these are things that you don't *want* to be easy, like shooting yourself in the kidney. (But these features are often described in ways that make them sound great, like "flexible usage of bullet-placement tools".) Inserting arbitrary print statements into the middle of some code is difficult for a reason. -Brent

On Sat, Feb 04, 2012 at 12:23:07PM -0600, Qi Qi wrote:
Hello,
I have a question;how can I print out the intermediate number lists in a mergesort recursive function like the following one.
merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
mergesort [] = [] mergesort [x] = [x] mergesort xs = let (as, bs) = splitAt (length xs `quot` 2) xs in merge (mergesort as) (mergesort bs)
main = do print $ mergesort [5,4,3,2,1]
In the main function, it only prints out the final number list. But I'd like to print out the number lists in every recursive level. How can I do that? Thanks.
For visualizing intermediate steps for the purpose of debugging, there is also the very nice hood package: http://hackage.haskell.org/package/hood -Brent
participants (8)
-
Brent Yorgey
-
Ivan Lazar Miljenovic
-
MigMit
-
Ozgur Akgun
-
Qi Qi
-
Roman Cheplyaka
-
Steve Horne
-
yi huang