首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Haskell导管合并源

使用Haskell导管合并源
EN

Stack Overflow用户
提问于 2019-02-12 06:38:53
回答 2查看 155关注 0票数 3

是否有可能在管道中构建一个函数(例如zipC2)来转换以下源:

代码语言:javascript
运行
复制
series1 = yieldMany [2, 4, 6, 8, 16 :: Int]

series2 = yieldMany [1, 5, 6 :: Int]

生成以下对(如下面的列表所示):

代码语言:javascript
运行
复制
[(Nothing, Just 1), (Just 2, Just 1), (Just 4, Just 1), (Just 4, Just 5), (Just 6, Just 6), (Just 8, Just 6), (Just 16, Just 6)]

它将以下列方式使用比较函数调用:

代码语言:javascript
运行
复制
runConduitPure ( zipC2 (<=) series1 series1 .| sinkList )

以前的版本中有一个mergeSources函数,它做了一些相对类似的事情(虽然没有内存效应),但在最近的版本(1.3.1)中消失了。

说明函数是如何工作的:其思想是采用两个源A(生成值a)和B(生成值b)。

然后生成对:

如果a

如果b

如果一个== b,我们更新双方,我们生产(只是a,仅仅b)

未更新的源的值未被使用,并用于下一轮比较。只使用更新的值。

然后,根据来自A和B的相对于彼此的值,我们继续更新对。

换句话说:如果a< b,则更新对的左侧;如果b < a,则更新右侧;如果== b,则更新两边。任何未使用的值都保留在内存中,以便进行下一轮比较。

EN

Stack Overflow用户

回答已采纳

发布于 2019-02-12 09:49:58

我成功地创建了您的zipC2函数:

代码语言:javascript
运行
复制
import Data.Ord
import Conduit
import Control.Monad

zipC2Def :: (Monad m) => (a -> a -> Bool) -> ConduitT () a m () -> ConduitT () a m () -> (Maybe a, Maybe a) -> ConduitT () (Maybe a, Maybe a) m ()
zipC2Def f c1 c2 (s1, s2) = do
  ma <- c1 .| peekC
  mb <- c2 .| peekC
  case (ma, mb) of
    (Just a, Just b) ->
      case (f a b, f b a) of
        (True, True) -> do
          yield (ma, mb)
          zipC2Def f (c1 .| drop1) (c2 .| drop1) (ma, mb)
        (_, True) -> do
          yield (s1, mb)
          zipC2Def f c1 (c2 .| drop1) (s1, mb)
        (True, _) -> do
          yield (ma, s2)
          zipC2Def f (c1 .| drop1) c2 (ma, s2)
        _ ->
          zipC2Def f (c1 .| drop1) (c2 .| drop1) (ma, s2)
    (Just a, Nothing) -> do
      yield (ma, s2)
      zipC2Def f (c1 .| drop1) c2 (ma, s2)
    (Nothing, Just b) -> do
      yield (s1, mb)
      zipC2Def f c1 (c2 .| drop1) (s1, mb)
    _ -> return ()
  where
    drop1 = dropC 1 >> takeWhileC (const True)

zipC2 :: (Monad m) => (a -> a -> Bool) -> ConduitT () a m () -> ConduitT () a m () -> ConduitT () (Maybe a, Maybe a) m ()
zipC2 f c1 c2 = zipC2Def f c1 c2 (Nothing, Nothing)

main :: IO ()
main = 
  let
    series1 = yieldMany [2, 4, 6, 8, 16 :: Int] :: ConduitT () Int Identity ()
    series2 = yieldMany [1, 5, 6 :: Int] :: ConduitT () Int Identity ()
  in
  putStrLn $ show $ runConduitPure $
    (zipC2 (<=) series1 series2)
    .| sinkList

产出:

[(Nothing,Just 1),(Just 2,Just 1),(Just 4,Just 1),(Just 4,Just 5),(Just 6,Just 6),(Just 8,Just 6),(Just 16,Just 6)]

票数 1
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54644170

复制
相关文章

相似问题

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