gpt4 book ai didi

haskell 管道 : having a Sink return a value based on the values from upstream

转载 作者:行者123 更新时间:2023-12-02 17:07:21 25 4
gpt4 key购买 nike

我一直在尝试使用 Conduit 库来执行一些涉及文件的简单 I/O,但我遇到了困难。

我有一个文本文件,只包含几个数字,例如1234。我有一个使用 readFile (无管道)读取文件的函数,并返回 Maybe Int (当文件实际上不返回Nothing时)不存在)。我正在尝试编写一个使用管道的函数版本,但我无法弄清楚。

这是我所拥有的:

import Control.Monad.Trans.Resource
import Data.Conduit
import Data.Functor
import System.Directory
import qualified Data.ByteString.Char8 as B
import qualified Data.Conduit.Binary as CB
import qualified Data.Conduit.Text as CT
import qualified Data.Text as T

myFile :: FilePath
myFile = "numberFile"

withoutConduit :: IO (Maybe Int)
withoutConduit = do
doesExist <- doesFileExist myFile
if doesExist
then Just . read <$> readFile myFile
else return Nothing

withConduit :: IO (Maybe Int)
withConduit = do
doesExist <- doesFileExist myFile
if doesExist
then runResourceT $ source $$ conduit =$ sink
else return Nothing
where
source :: Source (ResourceT IO) B.ByteString
source = CB.sourceFile myFile

conduit :: Conduit B.ByteString (ResourceT IO) T.Text
conduit = CT.decodeUtf8

sink :: Sink T.Text (ResourceT IO) (Maybe Int)
sink = awaitForever $ \txt -> let num = read . T.unpack $ txt :: Int
in -- I don't know what to do here...

有人可以帮我完成sink功能吗?谢谢!

最佳答案

这并不是一个很好的例子,说明管道实际上提供了很多值(value),至少不是您现在看到的那样。具体来说,您尝试使用 read 函数,该函数要求整个值都位于内存中。此外,您当前的错误处理行为有点松散。本质上,如果内容中有任何意外的内容,您只会收到 read: no parse 错误。

但是,有一种方法可以在管道中使用它并且有意义:通过我们自己逐字节解析 ByteString 并避免 读取 函数。幸运的是,这种模式属于标准左折叠,导管组合器包提供了一个完美的功能(导管中的元素左折叠,又名 foldlCE):

{-# LANGUAGE OverloadedStrings #-}
import Conduit
import Data.Word8
import qualified Data.ByteString as S

sinkInt :: Monad m => Consumer S.ByteString m Int
sinkInt =
foldlCE go 0
where
go total w
| _0 <= w && w <= _9 =
total * 10 + (fromIntegral $ w - _0)
| otherwise = error $ "Invalid byte: " ++ show w

main :: IO ()
main = do
x <- yieldMany ["1234", "5678"] $$ sinkInt
print x

与此相关的还有很多警告:如果存在意外字节,它只会抛出异常,并且根本不处理整数溢出(尽管修复那个只是一个问题)将 Int 替换为 Integer 的问题)。需要注意的是,由于有效的 32 位或 64 位 int 的内存中字符串表示总是很小,因此管道对于这个问题来说是多余的,尽管我希望这段代码能够提供一些关于如何一般地进行操作的指导。编写管道代码。

关于 haskell 管道 : having a Sink return a value based on the values from upstream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28917108/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com