Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何通过流式ByteString跟踪进度?_Haskell_Pipe_Pipeline_Bytestring_Haskell Streaming - Fatal编程技术网

Haskell 如何通过流式ByteString跟踪进度?

Haskell 如何通过流式ByteString跟踪进度?,haskell,pipe,pipeline,bytestring,haskell-streaming,Haskell,Pipe,Pipeline,Bytestring,Haskell Streaming,我正在使用流式UTIL来流式传输HTTP响应体。我希望跟踪进度,类似于使用lazyByteStrings的方式。我怀疑这样做是必要的,然后减少一些累积字节的读取并返回原始流。但我无法理解,而且文档也毫无用处,大多都是与其他库的宏大比较 下面是一些我迄今为止尽最大努力编写的代码。它还没有包括计数,只是在数据流经过时尝试打印数据块的大小(并且不编译) download::ByteString->FilePath->IO() 下载i file=do req我们想要的是以两种方式遍历流(ByteStri

我正在使用流式UTIL来流式传输HTTP响应体。我希望跟踪进度,类似于使用lazy
ByteString
s的方式。我怀疑这样做是必要的,然后减少一些累积字节的读取并返回原始流。但我无法理解,而且文档也毫无用处,大多都是与其他库的宏大比较

下面是一些我迄今为止尽最大努力编写的代码。它还没有包括计数,只是在数据流经过时尝试打印数据块的大小(并且不编译)

download::ByteString->FilePath->IO()
下载i file=do

req我们想要的是以两种方式遍历
流(ByteString的)IO()

  • ByteString
    s的传入长度累加起来并将更新打印到控制台的一种
  • 将流写入文件的人
我们可以在函数的帮助下完成此操作,该函数具有以下类型:

copy
获取一个流并将其复制到两个不同的一元层,其中原始流的每个元素由新分离流的两个层发射

(请注意,我们正在更改基本单子,而不是函子。将函子更改为另一个
所做的是在一个流中更改,我们对此不感兴趣。)

下面的函数获取一个流,复制它,用它累积传入字符串的长度,并返回另一个仍然可以使用的流,例如将其写入文件:

{-# LANGUAGE OverloadedStrings #-}
import Streaming
import qualified Streaming.Prelude as S
import qualified Data.ByteString as B

track :: Stream (Of B.ByteString) IO r -> Stream (Of B.ByteString) IO r
track stream =
      S.mapM_ (liftIO . print) -- brings us back to the base monad, here another stream
    . S.scan (\s b -> s + B.length b) (0::Int) id
    $ S.copy stream
这将打印
ByteString
s以及累计长度:

main :: IO ()
main = S.mapM_ B.putStr . track $ S.each ["aa","bb","c"]

这有点令人兴奋。最初由S.copy返回的外部流将驱动内部流?@MattJoiner更像是元素在lockstep中发出。事实上,你可以使用
提升
来处理内部
首先:@MattJoiner,不管它值多少,
复制
扩展的一个特例::(单子m,函子f)=>(对于所有ab.(ga->b)->fa->hb)->流fmr->流g(流hm)r
。也许这会对你的直觉有所帮助。当然,它的实现更受其类型的限制。@danidiaz有可能使它成为非阻塞的吗?我想反复调用
track
,并以60FPS的速度在屏幕上显示下载进度(使用
(a->IO a)->IO()
功能)。
{-# LANGUAGE OverloadedStrings #-}
import Streaming
import qualified Streaming.Prelude as S
import qualified Data.ByteString as B

track :: Stream (Of B.ByteString) IO r -> Stream (Of B.ByteString) IO r
track stream =
      S.mapM_ (liftIO . print) -- brings us back to the base monad, here another stream
    . S.scan (\s b -> s + B.length b) (0::Int) id
    $ S.copy stream
main :: IO ()
main = S.mapM_ B.putStr . track $ S.each ["aa","bb","c"]