使用流媒体库为每个块添加延迟?

时间:2018-06-10 07:44:18

标签: haskell haskell-streaming

新手到Streaming和Haskell这里。

我一直在玩streaming库,我对理解块部分特别感兴趣。例如:

S.print $ S.delay 1.0 $ concats $ chunksOf 2 $ S.each [1..10]

或者:

S.print $ concats $ S.maps (S.delay 1.0) $ chunksOf 2 $ S.each [1..10]

这里我可以在每个元素之后引入延迟,但我想要的是在每个块之后有一个延迟,在这种情况下是每秒元素的延迟。我尝试了这个,但没有编译:

S.print $ concats $ S.delay 1.0 $ chunksOf 2 $ S.each [1..10]

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

我们需要的是一个在块流末尾插入单个延迟的函数,并将该函数传递给maps

delay在这里不起作用,因为它会在每个屈服值之间产生延迟。但我们可以使用Applicative

中的函数轻松完成
  S.print 
$ concats 
$ S.maps (\s -> s <* liftIO (threadDelay 1000000)) 
$ chunksOf 2 
$ S.each [1..10]

这里发生了什么? maps将转换应用于Stream的“基础仿函数”。在使用chunksOf获得的“分块流”中,该基础仿函数本身 a Stream。此外,转换必须保留Stream的返回值。

如果下一个流取决于前一个流的最终结果,则可以使用(>>=) :: Stream f m a -> (a -> Stream f m b) -> Stream f m b等函数对{p> Stream进行排序,如果不是,则使用(<*) :: Stream f m a -> Stream f m b -> Stream f m a等函数。 (<*)保留第一个Stream的返回值,这就是我们在这种情况下所需要的。

我们不想再产生任何元素,只是为了引入延迟效果,所以我们只需liftIO效果Stream monad。

Stream的每个屈服值之后插入延迟的另一种方法是zip it,延迟时间infinite list

delay' :: MonadIO m => Int -> Stream (Of a) m r -> Stream (Of a) m r
delay' micros s = S.zipWith const s (S.repeatM (liftIO (threadDelay micros)))