如何监视Haskell中的计算过程

Ser*_*nin 8 haskell

我的主要功能块中有一个功能

map anyHeavyFunction [list]
Run Code Online (Sandbox Code Playgroud)

我想在计算过程中显示进度条或添加其他操作(暂停,停止进程等),但因为map是纯函数我不能直接执行.我猜我必须使用monad,但是monad是合适的吗?IO,State

Dav*_*rak 8

我知道至少有一个关于hackage的库有一些预先制作的monad变换器来完成这个任务,但是我通常会在需要时转向管道包来自己滚动.我使用的是管道 - 4.0.0本周末将会出现在hackage上,但你可以在此之前从github repo中获取它.

我还使用了terminal-progress-bar包,这样它也可以制作一个漂亮的终端动画.

{-# language BangPatterns #-}

import Pipes
import qualified Pipes.Prelude as P

import Control.Monad.IO.Class

import System.ProgressBar
import System.IO ( hSetBuffering, BufferMode(NoBuffering), stdout )

-- | Takes the total size of the stream to be processed as l and the function
-- to map as fn
progress l = loop 0
  where
    loop n = do
        liftIO $ progressBar (msg "Working") percentage 40 n l
        !x <- await -- bang pattern to make strict
        yield x
        loop (n+1)

main = do
    -- Force progress bar to print immediately 
    hSetBuffering stdout NoBuffering
    let n = 10^6
    let heavy x = last . replicate n $ x -- time wasting function
    r <- P.toListM $ each [1..100] >-> P.map heavy >-> progress 100
    putStrLn ""
    return r
Run Code Online (Sandbox Code Playgroud)

这动画:

> Working [=>.......................]   7%

> Working [=====>...................]  20%
Run Code Online (Sandbox Code Playgroud)

每次更新都会删除最后一个栏,因此它只占用终端上的一行.然后它完成如下:

> main
Working [=========================] 100%
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]
Run Code Online (Sandbox Code Playgroud)