How to write a monad that prints “step i of N” when executing each statement in the monad?

后端 未结 5 1398
清歌不尽
清歌不尽 2021-02-15 10:38

I\'m not even sure this is possible in any kind of monad; does it violate monad laws? But it seems like something that should be possible in some kind of construct or other. S

5条回答
  •  余生分开走
    2021-02-15 11:18

    While I think Daniel Díaz' arrow solution is he perfect way to do this, there is sure enough a simpler one (which, I just see, he also indicates in the comments already) provided, as in your example, no data is passed between the different function calls.

    Remember that, since Haskell is lazy, functions can do lots of stuff that would require macros in other languages. In particular, it's no problem whatsoever to have a list of IO actions. (Absolutely safe, too: due to pureness, there's no way these could "go off early" in Haskell!) Then you can simply take the length of this list as the total count, interleave it with printing statements, and be done. All in the core language, don't need TH!

    sequenceWithStepCount :: [IO()] -> IO()
    sequenceWithStepCount actions = go actions 0
     where nTot = length actions
           go [] _ = putStrLn "Done!"
           go (act:remains) n = do
                 putStrLn ("Step "++show n++" of "++show nTot)
                 act
                 go remains $ succ n
    

    To be used like

    do
     sequenceWithStepCount [
         someOp ()
       , someOtherOp ()
       , thirdOp ()
       ]
    

提交回复
热议问题