我试图理解管道概念的不同实现之间的差异.导管和管道之间的区别之一是它们如何将管道熔合在一起.管道有
(>+>) :: Monad m
=> Pipe l a b r0 m r1 -> Pipe Void b c r1 m r2 -> Pipe l a c r0 m r2
Run Code Online (Sandbox Code Playgroud)
而管有
(>->) :: (Monad m, Proxy p)
=> (b' -> p a' a b' b m r) -> (c' -> p b' b c' c m r) -> c' -> p a' a c' c m r
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,使用管道,当两个管道的任何管道停止时,返回其结果而停止另一个.使用导管,如果左侧管道完成,其结果将向下游发送到右侧管道.
我想知道, …
Pipes.Aeson库公开以下函数:
decode :: (Monad m, ToJSON a) => Parser ByteString m (Either DecodingError a)
Run Code Online (Sandbox Code Playgroud)
如果我将evalStateT与此解析器和文件句柄作为参数一起使用,则会从文件中读取单个JSON对象并进行解析.
问题是文件包含几个对象(所有类型都相同),我想在阅读时折叠或缩小它们.
Pipes.Parse提供:
foldAll :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Parser a m b
Run Code Online (Sandbox Code Playgroud)
但是你可以看到这会返回一个新的解析器 - 我想不出提供第一个解析器作为参数的方法.
看起来Parser实际上是StateT monad变换器中的Producer.我想知道是否有一种从StateT中提取Producer的方法,以便evalStateT可以应用于foldAll Parser,以及解码Parser中的Producer.
这可能完全是错误的方法.
我的问题,简而言之:
使用Pipes.Aeson解析文件时,折叠文件中所有对象的最佳方法是什么?
我正在尝试使用管道和基于它构建的各种库来编写基本的网络服务器.预期的流程是:
从socket接收字节串 - >使用二进制解码 - >服务器逻辑在这里 - >发送响应到套接字
我认为这将是:
fromSocket s 4096 >-> decode >-> serverLogic >-> toSocket s
Run Code Online (Sandbox Code Playgroud)
管道二进制有一个decode和一个decodeMany,但我不确定我理解差异,我不知道如何使用decode.为什么decodeMany将上游管道作为参数而不是用它链接>->?你如何使用decode,StateT我的管道最终应该是什么样的?
我有一个小的Haskell Pipe打印出它运行了多少次:
counterPipe :: Pipe String String IO r
counterPipe = go 0
where
go n = do
await >>= yield
let n' = succ n
liftIO $ putStrLn $ "Chunk " ++ show n'
go n'
Run Code Online (Sandbox Code Playgroud)
我希望能够在处理完最后一个块后打印出一条消息,并可能执行其他任务.我该怎么做呢?
我有以下程序,在运行时不产生输出runhaskell Toy.hs,而是无限期挂起.根据我的理解,程序应该打印"hi"然后退出.我很感激有关如何调试此类问题的答案和/或建议.我正在使用Github的管道4.0.0(github.com/Gabriel439/Haskell-Pipes-Library).
module Toy where
import Pipes
import Control.Monad.State
type Request = String
type Response = String
serveChoice :: Request -> Server Request Response IO ()
serveChoice = forever go
where go req = do
lift $ putStrLn req
respond req
run :: Monad m => () -> Client Request Response (StateT Int m) ()
run () = do
request "hi"
return ()
main :: IO ()
main = evalStateT (runEffect $ hoist lift . serveChoice …Run Code Online (Sandbox Code Playgroud) 有时需要执行一些复杂的例程来检索或保存正在处理的数据.在这种情况下,人们想要分离数据生成和数据处理逻辑.常见的方法是使用类似iteratee的功能.有很多不错的图书馆:管道,管道等.在大多数情况下,他们会做这件事.但是AFAIK它们(除了,可能是管道)受到处理顺序的限制.
但考虑一个日志查看器示例:人类可能希望随机来回漫步.他也可以放大和缩小.我担心迭代者在这里无能为力.
一个简单的解决方案可能如下所示:
-- True is for 'right', 'up', etc. and vice versa
type Direction = Bool
class Frame (f :: * -> *) where
type Dimension f :: *
type Origin f :: * -> *
grow', shrink' move' :: Monad m => Dimension f -> Direction -> f a -> m (f a)
move' dim dir f = grow' dim dir f >>= shrink' dim (not dir)
liftF' :: (Origin f a -> b) -> f a -> …Run Code Online (Sandbox Code Playgroud) 这是包Effect的官方教程中提供的图表pipes.
type Effect = Proxy X () () X
Upstream | Downstream
+---------+
| |
X <== <== ()
| |
() ==> ==> X
| | |
+----|----+
v
r
Run Code Online (Sandbox Code Playgroud)
由于Effect没有任何数据流,我期待它只是Proxy X X X X,密封所有流量.但相反,它允许两个流入.这有什么特别的原因吗?如果我只是Effect通过签名来编写通常所做的事情Proxy X X X X,它可以完美地传递编译器:
myMonad :: Proxy X X X X IO ()
myMonad = do
a <- lift $ getLine
lift $ print a
return ()
Run Code Online (Sandbox Code Playgroud)
为什么我们不能run这样呢?
说我有这个代码:
import Control.Monad.State hiding (StateT)
import Control.Proxy
server :: (Proxy p, Monad m) => Int -> Server p Int Bool (StateT Int m) ()
server = runIdentityK loop
where loop arg = do
currMax <- lift get
lift $ put $ max currMax arg
nextArg <- respond (even arg)
loop nextArg
client :: (Proxy p, Monad m) => Client p Int Bool m ()
client = runIdentityP loop
where loop = go 1
go i = do
isEven <- request …Run Code Online (Sandbox Code Playgroud) 我试图弄清楚管道教程中提到的一个例子ListT:
import Pipes
import qualified Pipes.Prelude as P
input :: Producer String IO ()
input = P.stdinLn >-> P.takeWhile (/= "quit")
name :: ListT IO String
name = do
firstName <- Select input
lastName <- Select input
return (firstName ++ " " ++ lastName)
Run Code Online (Sandbox Code Playgroud)
如果运行上面的示例,我们得到如下输出:
>>> runEffect $ every name >-> P.stdoutLn
Daniel<Enter>
Fischer<Enter>
Daniel Fischer
Wagner<Enter>
Daniel Wagner
quit<Enter>
Donald<Enter>
Stewart<Enter>
Donald Stewart
Duck<Enter>
Donald Duck
quit<Enter>
quit<Enter>
>>>
Run Code Online (Sandbox Code Playgroud)
看起来:
Select input)在读取输入时轮流(可能是非确定性的).