我正在逐个字符地阅读文件,我想在我的代码中将所有这些字符组合在一个名为fullstr的字符串中。我需要通过组合一个字符串中的所有字符来以字符串形式提供整个文件。我已经尝试通过跳过\ n 。 这是我的代码。
module TreasureFile where
import System.IO
main = do
hdl <- openFile "map.txt" ReadMode
readbychar hdl
readbychar hdl = do t <- hIsEOF hdl
if t then return()
else do
x <- hGetChar hdl
if x =='\n' then return()
else do
let char = charToString x
let fullstr = makestr fullstr char
readbychar hdl
charToString :: Char -> String
charToString c = [c]
makestr :: String->String->String
makestr c d =do
let e=c ++ d
return e
答案 0 :(得分:3)
首先,这不会发生变形。首先,您似乎对使用return
感到困惑。有些人可能会说这个函数命名很差,因为它似乎模仿return
在其他语言中的行为,但在Haskell中它只不过是一个常规函数。例如,您可以非常轻松地执行以下操作
x :: IO String
x = do
return ()
return 1
return Nothing
return False
return "It worked"
如果你要做的话
main :: IO ()
main = do
s <- x
putStrLn s
它会将It worked
打印到屏幕上。在Haskell中,return
只不过是monadic类型的构造函数。它需要一个值,并根据类型签名将其包装在适当的monadic上下文中。所以我也可以写
x :: Maybe String
x = do
return ()
return 1
return Nothing
return False
return "It worked"
然后
main :: IO ()
main = do
case x of
Just s -> putStrLn s
Nothing -> putStrLn "Never reached"
请注意,在此上下文中,x
与其他纯值匹配,而不是被绑定符号IO
视为<-
操作。
另一个问题是,您似乎试图在循环的每次迭代中修改fullstr
。在Haskell中,值是不可变的,在分配后不能更改它们。可以说Haskell没有变量,只有名称绑定到值。在这里,您实际上是使用表达式
fullstr
let fullstr = makestr fullstr char
这个计算永远不会完成,它会陷入无限的递归循环中。此外,您永远不会在任何地方返回fullstr
,您只是分配它,然后继续readbychar
中的循环的下一次迭代。你可以更简单地解决这个问题,如果你想阅读文件的第一行,只需使用readFile
:
main :: IO ()
main = do
contents <- readFile "map.txt"
let firstLine = takeWhile (/= '\n') contents
putStrLn firstLine
如果您希望列表中的每一行文件,只需在其上调用lines
:
main :: IO ()
main = do
contents <- readFile "map.txt"
let allLines = lines contents
mapM_ putStrLn allLines -- mapM_ is like map but for monadic functions
答案 1 :(得分:0)
这已经写成库函数hGetContents
您可以像以下一样使用它:
import System.IO (ReadMode, openFile, hGetContents)
main :: IO ()
main = do
hdl <- openFile "map.txt" ReadMode
cnts <- hGetContents hdl
doSomethingWith cnts
doSomethingWith :: String -> IO ()
doSomethingWith = error "You didn't say what you wanted to do."
最终,您可能希望避免半封闭状态。你可以这样做:
import Control.Exception (bracket)
import System.IO (ReadMode, openFile, hGetContents, hClose)
safeDeinterleaveIO :: IO [a] -> IO [a]
safeDeinterleaveIO act = do
interleaved <- act
return $! length interleaved `seq` interleaved
main :: IO ()
main = do
cnts <- bracket acquire release use
doSomethingWith cnts
where
acquire = openFile "map.txt" ReadMode
use = safeDeinterleaveIO . hGetContents
release = hClose
或者,您可以学习像conduit
,pipes
或io-streams
这样的流媒体库。