haskell - 为简单函数管道等效代码

标签 haskell haskell-pipes

比方说,我有以下类型:

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 的 Producers,我如何通过这两个在 Pipes 世界中实现上面的 getSnaps 功能制作人:

psnap :: Producer Snap IO ()
psnap = undefined

plink :: Producer Link IO ()
plink = undefined

psnapplink的实际类型比较复杂(使用attoparsec-pipes创建出来),但我想知道如何实现getSnaps的功能来自 psnapplink。有解决此类问题的正确方法吗?

最佳答案

我提出的解决方案与您的代码非常相似。我刚刚将 map 替换为 Pipes.Prelude.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'。这样做的原因是我们要重复使用列表的内容,所以我们需要将整个列表缓存在内存中,以便重复使用。

关于haskell - 为简单函数管道等效代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24663098/

相关文章:

haskell - 管道展开组成

json - 使用 Pipes.Aeson 在 Haskell 中对 JSON 进行流式解析

haskell - 这是多用户网络服务器的合理架构吗? (管道并发引入了多少开销?)

haskell - 跳过管道 attoparsec 中的第一行

haskell - 封闭类型类是否足以推断关联类型(没有类型族)?

haskell - 如何让 Haskell QuickCheck 2.4 增加 # 个测试?

haskell - 简单的解析示例会产生类型错误

haskell - 向下游发信号表明上游已用尽

haskell - 如何在纯函数中选择随机列表元素?

haskell - 如何使用 haskell 堆栈创建一个 nix 包