3

我在使用以下代码时遇到问题network-conduit

import Data.Conduit.List as CL
import Data.Conduit.Text as CT
import qualified Data.ByteString.Char8 as S8
import qualified Data.Text as TT

mySource :: ResourceT m => Integer -> Source m Int
mySource i = {- function -} undefined

myApp :: Application
myApp src snk = 
    src $= CT.decode CT.ascii
        $= CL.map decimal
        $= CL.map {-problem here-}
        $$ src

在有问题的地方我想写一些类似的东西

\t -> case t of
    Left err = S8.pack $ "Error:" ++ e
    Right (i,xs) = (>>>=) mySource 
                 {- or better: 
                   do 
                   (>>>=) mySource
                   (<<<=) T.pack xs
                  -}

(>>>=)函数将mySource输出推送到下一级 并将(<<<=)函数发送回上一级

4

1 回答 1

1

网络将字节流切成任意ByteString块。使用上面的代码,这些ByteString块将被映射到块Text,并且每个块Text将被解析为decimal. 但是,表示单个十进制数字的字符串decimal可以分成两个(或更多)Text块。此外,正如您所意识到的, using会将未解析为 的一部分decimal的剩余块返回给您,您正试图将其推回输入流中。Textdecimal

这两个问题都可以通过使用Data.Conduit.Attoparsec. conduitParserEitherwith来解决Data.Attoparsec.Text.decimal。请注意,仅解析是不够的decimal;您还需要处理 s 之间的某种分隔符decimal

也不能拼接Sourcefrom CL.map,因为CL.map的类型签名是

map :: Monad m => (a -> b) -> Conduit a m b

您传递给的函数map有机会将每个输入a转换为单个输出b,而不是b's 流。为此,您可以使用awaitForever,但您需要将您的Source转换为通用ProducerwithtoProducer才能匹配类型。

但是,在您的代码中,您尝试将解析错误发送到下游,但asByteString的输出是类型错误。在这两种情况下,您都必须提供一个流;成功的解析案例可以返回 a通过融合其他's 只要它以以下输出结束:mySourceIntByteStringConduitConduitByteString

...
$= (let f (Left err) = yield $ S8.pack $ "Error: " ++ show err
        f (Right (_, i)) = toProducer (mySource i) $= someOtherConduit
    in awaitForever f)

wheresomeOtherConduit接收Int's frommySource和 sources ByteString's。

someOtherConduit :: Monad m => Conduit Int m ByteString

最后,我相信你的意思是snk在管道的末端连接而不是src.

于 2017-11-27T21:13:48.717 回答