Search code examples
haskellfrp

How should I output values from a list as they are calculated?


I have a long-running computation that outputs a list. I want to output values from this list as they are computed. What would be a neat way to do this?

Currently I use mapM_ print to print each value to STDOUT. This works well enough for the simple case of printing values to the command line, but feels a little bit hacky and hard to work with.

Additionally, at some point, I want to turn my command-line output into an interactive visualization. How could I go about turning my list into something like a stream of events from FRP? Being able to plug this into an existing GUI framework as a source of events would be great.

Rewriting the function to use something other than a list is an option, although a solution that allows me to take the list as-is would be ideal.


Solution

  • This is a job for iteratees and iteratees like libraries.

    Using the Proxy library.

    import Control.Proxy
    
    runProxy $ fromListS [1..10] >-> <processing> >-> printD >-> <more> processing>
    

    Where <processing> is the addition calculations you need to make.

    Similar questions: lazy version of mapM, Is Haskell's mapM not lazy?

    For example:

    > labeledPrint label x = putStrLn $ label ++ show x
    > runProxy $ fromListS [1..4] >-> printD >-> mapD (*2) 
                                  >-> useD (labeledPrint "Second printer: ")
    1
    Second printer: 2
    2
    Second printer: 4
    3
    Second printer: 6
    4
    Second printer: 8
    

    If you reverse the order of application and use <-< instead of >-> then it looks like normal function application.

    runProxy $ useD (labeledPrint "Second printer: ") <-< mapD (*2)
                                                      <-< printD
                                                      <-< fromListS [1..4]