首页 文章

管道简单函数的等效代码

提问于
浏览
2

比方说,我有以下类型:

type LinkID = Int

data Link = Link {
  lid :: LinkID,
  llength :: Int
  }

data Snap = Snap {
  slid :: LinkID,
  slength :: Int
  }

现在,我想编写一个基于管道的函数来执行此操作:

getSnaps :: LinkID -> [Link] -> [Snap] -> [(LinkID, [Snap])]
getSnaps l lks snp = map (\x -> (lid x, filter (\y -> lid x == slid y) snp)) a
  where a = filter (\x -> lid x > l) lks

假设我已经拥有了 LinkSnap 的制作人,我怎样才能从这两个制作人的管道世界中实现上述 getSnaps 功能:

psnap :: Producer Snap IO ()
psnap = undefined

plink :: Producer Link IO ()
plink = undefined

psnapplink 的实际类型更复杂(通过使用attoparsec-pipes创建),但我想知道如何从 psnapplink 实现getSnaps的功能 . 有没有正确的方法来解决这类问题?

1 回答

  • 2

    我提出的解决方案与您的代码非常相似 . 我刚用 Pipes.Prelude.map 替换 map ,用 Pipes.Prelude.filter 替换了其中一个过滤器:

    import Pipes
    import qualified Pipes.Prelude as Pipes
    
    type LinkID = Int
    
    data Link = Link
        { lid :: LinkID
        , llength :: Int
        }
    
    data Snap = Snap
        { slid :: LinkID
        , slength :: Int
        }
    
    getSnaps
        :: Monad m
        => LinkID
        -> Producer  Link            m ()
        -> Producer  Snap            m ()
        -> Producer (LinkID, [Snap]) m ()
    getSnaps l lks snp = do
        snp' <- lift (Pipes.toListM snp)  -- Cache `snp` into the list `snp'`
        lks >-> Pipes.filter (\x -> lid x > l)
            >-> Pipes.map (\x -> (lid x, filter (\y -> lid x == slid y) snp'))
    

    请注意,有一个非平凡的部分,即上述解决方案严格地将 snp Producer 的内容加载到列表 snp' 中 . 原因是我们必须重复使用列表的内容,因此我们需要将整个列表缓存在内存中以便重复使用 .

相关问题