4

流式Stream库的简化(无效)定义如下所示:

data Stream f = Step (f (Stream f))
              | Return

我试图了解引入这个函子的动机f是什么。

一个典型的例子fOf aOf定义为

data Of a b = !a :> b
    deriving Functor

当我读到这种有意义的定义时,f就像Of aan后跟more 可以从. 有了这种解释,定义中的. 但在这种情况下,一个更简单的版本应该是StreamOf a babf (Stream f)StreamOf a (Stream (Of a))

data Stream a = Step a (Stream a)
              | Return

我很难理解为什么要使用这个函子的泛化f。作者在介绍中说Stream

...可用于流式传输以任何函子为特征的连续不同步骤f

一般类型Stream f m r表示一连串的步骤......其形状由“函子”参数确定f

但在Streaming.Prelude中,我能找到的唯一函子是Or a,Stream (Of a) mIdentity。第一个是as 的流,第二个是流的流,第三个实现'erasure'

我真的不明白。我可以实现所有这些事情,即简单的as 流、流的流和擦除,而无需fStream.

这个函子f做了什么不能做的事情?

4

1 回答 1

1

流式分组功能的一个关键特性是它们不会强迫您在任何时候将整个组保存在内存中。他们以“流式传输”的方式进行分组。一旦检测到新组的开始,您就可以开始“下游”处理组。

例如,想象一个像lines :: Stream (Of Text) IO r -> Stream (Stream (Of Text) IO) IO r. 每当它检测到流中的换行符时,该函数将启动一个新组,即使新行的结尾还没有实现

Stream (Stream (OfText类型) IO) IO r的优点是,要到达当前行之后的行,我们必须完全消耗当前行。这是因为“流的其余部分”在于函子参数的结果值。并且Streams 只有在用尽了之后才放弃他们的结果。

likeStream (Of (Stream (Of a) IO ()) IO ()不会强迫我们在移动到下一行之前用完当前行。我们可以简单地忽略Stream在外部之前产生的内部Stream。但是那个“下一行”甚至可能还不存在,因为我们还没有真正阅读过之前的内容!也许这个方案可以以某种方式工作,但语义会不太清楚,需要用户提供更多的知识。


诸如mapped让我们使用定义为“上游”的“下游”组之类的功能。例如,此代码从stdin读取字符串,其中字符串“-”是组分隔符。下游代码将字符串解析为Ints 并在遇到 a 时显示一条消息5。请注意,消息显示在上游关闭组之前。

    import Streaming
    import qualified Streaming.Prelude as S

    example :: Stream (Of ()) IO () 
    example = 
        let upstream :: Stream (Stream (Of String) IO) IO ()
            upstream = S.breaks (=="-") S.stdinLn
            downstream :: Stream (Stream (Of String) IO) IO () 
                       -> Stream (Of ()) IO ()
            downstream = S.mapped handleGroup
            handleGroup :: Stream (Of String) IO r ->
                           IO (Of () r)
            handleGroup stream = do
                print "group began" 
                r <- S.effects
                   . S.chain (\_ -> putStrLn "found!") 
                   . S.filter (==5) 
                   . S.map (read @Int) 
                   $ stream 
                print "group ended"
                return (() :> r)
         in downstream upstream

    main :: IO ()
    main = S.effects example
于 2019-11-26T08:06:24.830 回答