我刚刚从最新的来源安装了GHC,现在我的程序给了我一个关于"关闭句柄的延迟读取"的错误消息.这是什么意思?
这是一个菜鸟问题.
我想写一个提供懒惰图像流的函数,大概是这样的:
imageStream :: [IO Image]
Run Code Online (Sandbox Code Playgroud)
不幸的是,读取图像的功能可能会失败,所以它看起来像:
readImage :: IO (Maybe Image)
Run Code Online (Sandbox Code Playgroud)
所以,我能写的功能如下:
maybeImageStream :: [IO (Maybe Image)]
Run Code Online (Sandbox Code Playgroud)
如何在保持惰性IO的同时实现如下功能?
flattenImageStream :: [IO (Maybe Image)] -> [IO Image]
Run Code Online (Sandbox Code Playgroud)
从语义上讲,当您要求flattenImageStream下一个图像时,它应该遍历列表并尝试读取每个图像.它会在找到加载并返回的图像之前执行此操作.
编辑:答案中似乎存在一些分歧.有些人建议使用的解决方案sequence,但我很确定我测试了它,并发现它破坏了懒惰.(我会再次测试它,以确保我何时回到我的电脑.)有人还建议使用unsafeInterleaveIO.从该函数的文档来看,它似乎可行,但显然我想尽可能地尊重类型系统.
在我对Haskell中抓住懒惰IO的哀悼中,我尝试了以下方法:
main = do
chars <- getContents
consume chars
consume :: [Char] -> IO ()
consume [] = return ()
consume ('x':_) = consume []
consume (c : rest) = do
putChar c
consume rest
Run Code Online (Sandbox Code Playgroud)
它只是回显了所有在stdin中键入的字符,直到我点击'x'.
所以,我天真地认为应该可以getContents通过getChar以下几点做一些事情来重新实现:
myGetContents :: IO [Char]
myGetContents = do
c <- getChar
-- And now?
return (c: ???)
Run Code Online (Sandbox Code Playgroud)
事实证明它不是那么简单,因为它???需要一个类型的功能IO [Char] -> [Char]- 我认为 - 打破IO monad的整个想法.
检查getContents(或更确切地说hGetContents)的实施揭示了整个香肠工厂的脏IO东西.我的假设是否正确,myGetContents如果不使用脏的,即monad-breaking代码, 就无法实现?
我有下一个monad变换器:
newtype Pdf' m a = Pdf' {
unPdf' :: StateT St (Iteratee ByteString m) a
}
type Pdf m = ErrorT String (Pdf' m)
Run Code Online (Sandbox Code Playgroud)
基本上,它使用底层 Iteratee来读取和处理pdf文档(需要随机访问源,因此它不会一直将文档保存在内存中).
我需要实现一个保存pdf文档的函数,我希望它是懒惰的,应该可以将文档保存在常量内存中.
我可以生产懒惰ByteString:
import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as BS
save :: Monad m => Pdf m ByteString
save = do
-- actually it is a loop
str1 <- serializeTheFirstObject
storeOffsetForTheFirstObject (BS.length str1)
str2 <- serializeTheSecondObject
storeOffsetForTheSecondObject (BS.length str2)
...
strn <- serializeTheNthObject
storeOffsetForTheNthObject (BS.length strn)
table <- dumpRefTable
return …Run Code Online (Sandbox Code Playgroud) 我需要就地修改文件.所以我打算读取文件内容,处理它们,然后将输出写入同一个文件:
main = do
input <- readFile "file.txt"
let output = (map toUpper input)
-- putStrLn $ show $ length output
writeFile "file.txt" output
Run Code Online (Sandbox Code Playgroud)
但问题是,只有当我取消注释第4行时才会按预期工作 - 我只是输出字符数到控制台.如果我不取消注释,我会得到
openFile: resource busy (file is locked)
Run Code Online (Sandbox Code Playgroud)
有没有办法强制阅读该文件?
我有以下Haskell程序用于计算整数字符串的最大和子串:
{-# LANGUAGE BangPatterns #-} {-# OPTIONS_GHC -O2 #-}
import Data.Functor
import Data.Maybe
import Data.ByteString.Lazy.Char8 (getContents,lines,readInt,words)
import Prelude hiding (getContents,words,lines)
main = do
cont <- words <$> getContents
putStrLn $ show $ snd $ foldl opt (0,0) $ map (fst.fromJust.readInt) cont
opt (!c,!m) x = (max 0 (c+x),max m (c+x))
Run Code Online (Sandbox Code Playgroud)
该程序的问题在于它将整个文件读入内存.没有BytesString的相应程序没有这个问题:
{-# LANGUAGE BangPatterns #-} {-# OPTIONS_GHC -O2 #-}
import Data.Functor
import Data.Maybe
main = do
cont <- words <$> getContents
putStrLn $ show $ snd $ foldl opt (0,0) …Run Code Online (Sandbox Code Playgroud) 我试图在Parsec一大堆小文件上运行一个解析器,并收到一条错误,说我有太多打开的文件.我知道我需要使用严格的IO,但我不知道该怎么做.这是有问题的代码:
files = getDirectoryContents historyFolder
hands :: IO [Either ParseError [Hand]]
hands = join $ sequence <$> parseFromFile (many hand) <<$>> files
Run Code Online (Sandbox Code Playgroud)
注意:我的<<$>>功能是这样的:
(<<$>>) :: (Functor f1, Functor f2) => (a -> b) -> f1 (f2 a) -> f1 (f2 b)
a <<$>> b = (a <$>) <$> b
Run Code Online (Sandbox Code Playgroud) 我正在使用http-client教程使用 TLS 连接获取响应正文。既然我可以观察到它print是由 调用的withResponse,为什么不print强制对以下片段中的输出进行完整响应?
withResponse request manager $ \response -> do
putStrLn $ "The status code was: " ++
body <- (responseBody response)
print body
Run Code Online (Sandbox Code Playgroud)
我需要写这个:
response <- httpLbs request manager
putStrLn $ "The status code was: " ++
show (statusCode $ responseStatus response)
print $ responseBody response
Run Code Online (Sandbox Code Playgroud)
我要打印的正文是一个懒惰的 ByteString。我仍然不确定是否应该print打印整个值。
instance Show ByteString where
showsPrec p ps r = showsPrec p (unpackChars ps) r
Run Code Online (Sandbox Code Playgroud) 我想重写该interact函数,但使用Text代替String。是否可以使用Data.Text和/或Data.Text.Lazy完成与相同的行为interact?
例如,当我使用来运行该程序时String:
main = interact (unlines . map f . lines)
where f "hello" = "wassup"
f _ = "wat?"
Run Code Online (Sandbox Code Playgroud)
它等待一行输入,然后打印出一行作为响应,并等待下一行输入。我想编写相同的代码并使其工作Text。
{-# LANGUAGE OverloadedStrings #-}
import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy as T
textInteract :: (Text -> Text) -> IO ()
textInteract = undefined
main = textInteract (T.unlines . map f . T.lines)
where f "hello" = "wassup"
f _ = "wat?"
Run Code Online (Sandbox Code Playgroud)
但是,不只是textInteract …
haskell ×9
lazy-io ×9
bytestring ×1
conduit ×1
file-io ×1
ghc ×1
http-conduit ×1
locking ×1
long-lines ×1
parsec ×1
text ×1