haskell - 是否可以使用每次等待一次的受限管道?

标签 haskell haskell-pipes

我正在与 pipes-4.0.0 合作。在该库中,yields 的数量管道下游的管道通常与 awaits 的数量无关。来自上游。

但是假设我想构建一个受限管道,强制为每个等待执行一个且仅一个yield,同时仍然能够使用单子(monad) (>>=) 对这些类型的管道进行排序。

我观察到,在双向情况下,每个值 requested来自上游的代理与发送回的值相匹配。所以也许我正在寻找的是一个 Proxy a' a () b m r -> Pipe a (Either b a') m r 类型的函数,它“反射(reflect)”上游的值,将它们转换为为下游带来额外的产量。或者,不太常见的是,Client a' a -> Pipe a a'。这样的功能可以吗?

最佳答案

您绝对不想为此使用管道。但是,您可以做的是定义一个执行此操作的受限类型,在该受限类型内执行所有连接和逻辑,然后在完成后将其提升为Pipe .

您想要的类型是这个,它类似于 netwire Wire:

{-# LANGUAGE DeriveFunctor #-}

import Control.Monad.Trans.Free  -- from the 'free' package

data WireF a b x = Pass (a -> (b, x)) deriving (Functor)

type Wire a b = FreeT (WireF a b)

这自动成为一个 monad 和一个 monad 转换器,因为它是根据 FreeT 实现的。然后就可以实现这个方便的操作了:

pass :: (Monad m) => (a -> b) -> Wire a b m ()
pass f = liftF $ Pass (\a -> (f a, ()))

...并使用一元语法组装自定义连线:

example :: Wire Int Int IO ()
example = do
    pass (+ 1)
    lift $ putStrLn "Hi!"
    pass (* 2)

然后,当您完成与此受限 Wire 类型的连接后,您可以将其提升为 Pipe:

promote :: (Monad m) => Wire a b m r -> Pipe a b m r
promote w = do
    x <- lift $ runFreeT w
    case x of
        Pure r -> return r
        Free (Pass f) -> do
            a <- await
            let (b, w') = f a
            yield b
            promote w'

请注意,您可以定义身份、导线和导线组合:

idWire :: (Monad m) => Wire a a m r
idWire = forever $ pass id

(>+>) :: (Monad m) => Wire a b m r -> Wire b c m r -> Wire a c m r
w1 >+> w2 = FreeT $ do
    x <- runFreeT w2
    case x of
        Pure       r   -> return (Pure r)
        Free (Pass f2) -> do
            y <- runFreeT w1
            case y of
                Pure       r   -> return (Pure r)
                Free (Pass f1) -> return $ Free $ Pass $ \a ->
                        let (b, w1') = f1 a
                            (c, w2') = f2 b
                        in  (c, w1' >+> w2')

我很确定它们构成了一个类别:

idWire >+> w = w

w >+> idWire = w

(w1 >+> w2) >+> w3 = w1 >+> (w2 >+> w3)

此外,我非常确定 promote 遵守以下仿函数定律:

promote idWire = cat

promote (w1 >+> w2) = promote w1 >-> promote w2

关于haskell - 是否可以使用每次等待一次的受限管道?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18946625/

相关文章:

haskell - 为什么 Haskell 无法自动解析参数数量?

haskell - 使用管道解析来保留 map 的剩余内容

haskell - 管道的剩菜有什么好处?

haskell - 带 Haskell 管道的有状态生成器

haskell - 用 Haskell 编码 "Less Than"

haskell - Cabal 中的 "Either A or B"依赖项

haskell - 评估 "main = return (getChar, getChar)"

linux - 在 Linux 上的 ghci 中读取标准输入被破坏

Haskell Control.Proxy.TCP 生产者

Haskell Pipes - 获取管道中最后一个代理的返回值