首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >导管:将两个源连接成一个

导管:将两个源连接成一个
EN

Stack Overflow用户
提问于 2016-10-31 11:26:13
回答 1查看 247关注 0票数 3

我有两个管道源A和B,我想把它们合并成一个屈服点:

代码语言:javascript
复制
data Result = Left Int | Value Int | Right Int

merge :: Monad m => Source m Int -> Source m Int -> Source Result
merge a b = undefined

如:

  • 使用来自ab的值。
  • 执行一些计算来生成Value Int
  • 作为计算的结果,ab都可以有一个leftover
  • 当其中一个序列耗尽时,结果源应该继续生成LeftRight值(取决于原始源仍然有值),直到两个源都耗尽为止。

我尝试用ZipSource实现它,例如:

代码语言:javascript
复制
getZipSource (ZipSource (a =$= CL.map Left) <* ZipSource (b =$= CL.map Right))

但是,我不知道如何使它在源之间交替(当我执行两个await),以及如何以我前面描述的方式处理剩菜。

我也看过sequenceSources,但它似乎也没有帮助。

这样的东西能用管道建造吗?

一个具体的例子是:

  • 有两个(假定排序的) Int
  • 从两者中获取值并进行比较
  • 生成min值,从最大值减去它,并将剩余值返回到它的流中
  • 重复一遍。

预期产出将是:

代码语言:javascript
复制
runConduit $ merge (CL.sourceList [10, 20, 30]) (CL.sourceList [6, 4, 20]) $$ CL.take 10

Value 6    -- 10-6  = 4,  6 yielded, 4 goes back to "a"
Value 4    -- 4-4   = 0,  both values are fully consumed
Value 20   -- 20-20 = 0,  both values are fully consumed
Left 30    -- "b" has no values, but "a" still yielding

到目前为止,我发现的最好的方法是编写类似于zipSources,将其内部结构调整为:

代码语言:javascript
复制
go (Done ()) (HaveOutput src close y) = HaveOutput (go (Done ()) src) close (Nothing, Just y)
go (HaveOutput src close x) (Done ()) = HaveOutput (go src (Done ())) close (Just x, Nothing)

这是正确的方法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-04 06:18:07

我就这样做了:

代码语言:javascript
复制
data MergedValue a v b = BackL a v | MergedValue v | BackR v b
data JoinResult a v b = LeftoverL a | JoinValue v | LeftoverR b

joinSources :: Monad m
            => (a -> b -> MergedValue a v b)
            -> Source m a
            -> Source m b
            -> Source m (JoinResult a v b)
joinSources f as bs =
  go (newResumableSource as) (newResumableSource bs)
  where
    go ras rbs = do
      (ras', ma) <- lift $ ras $$++ await
      (rbs', mb) <- lift $ rbs $$++ await
      case (ma, mb) of
        (Nothing, Nothing) -> pure ()
        (Nothing, Just b)  -> yield (LeftoverR b) >> go ras' rbs'
        (Just a,  Nothing) -> yield (LeftoverL a) >> go ras' rbs'
        (Just a,  Just b)  -> case f a b of
          BackL x v -> do
            yield (JoinValue v)
            (nxt, _) <- lift $ ras' $$++ leftover x
            go nxt rbs'
          BackR v x -> do
            yield (JoinValue v)
            (nxt, _) <- lift $ rbs' $$++ leftover x
            go ras' nxt
          MergedValue v -> yield (JoinValue v) >> go ras' rbs'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40341242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档