结合人物

时间:2014-07-29 18:19:53

标签: haskell

我正在逐个字符地阅读文件,我想在我的代码中将所有这些字符组合在一个名为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                      

2 个答案:

答案 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

或者,您可以学习像conduitpipesio-streams这样的流媒体库。