我有一个程序,根据给出的参数以不同的方式工作:
这是代码:
main :: IO ()
main = do
-- Read given arguments
args <- getArgs
-- If file containing gramma was given
if length args == 2 then do
hfile <- openFile (last args) ReadMode
content <- hGetContents hfile
let inGramma = getGramma content
doJob (head args) inGramma
hClose hfile
return ()
-- If no file was given - reads from stdin
else if length args == 1 then do
content <- getContents
let inGramma = getGramma content
doJob (head args) inGramma
return ()
else do putStrLn "Invalid count of arguments!"
问题是,当它从stdin读取时,在每个新行(输入按下)之后,它打印该行而不是下一个读取。我需要它等待整个输入而不是打印出来(在Ctrl + D之后)。
以下是该代码中使用的函数:
-- | Structure of gramma
data GrammaStruct = Gramma
{ nonTerminals :: NonTerminals
, terminals :: Terminals
, start :: Start
, rules :: Rules
} deriving (Eq)
-- | Representation of gramma
instance Show GrammaStruct where
show (Gramma n t s r) =
init (showSplit n) ++
"\n" ++ init (showSplit t) ++
"\n" ++ showStart s ++
"\n" ++ init (showRules r)
-- | Print gramma
showGramma :: GrammaStruct -> IO ()
showGramma gr = do
putStrLn $ show gr
-- | Transforms string given from file of stdin into gramma representation in app
getGramma :: String -> GrammaStruct
getGramma hIn = procLns (lines hIn)
-- | Depending on option given, provides required functionality
doJob :: String -> GrammaStruct -> IO ()
doJob op gramma
| op == "-i" = showGramma gramma
谢谢。
答案 0 :(得分:4)
这里的问题是getContents
使用惰性IO,使得输入流逐行处理。如果要在开始执行作业之前强制它读取整个输入,可以使用以下hack:
...
if length args == 1 then do
content <- getContents
length content `seq` return () -- force the input to be fully read now
let inGramma = getGramma content
doJob (head args) inGramma
return ()
或者,使用evaluate
,或者在Hackage中查找提供严格getContents
的严格IO模块。例如,我刚发现提供System.IO.Strict.getContents
的strict-io
包。使用它你应该能够写(未经测试)
import qualified System.IO.Strict as S
...
if length args == 1 then do
content <- run S.getContents
...
答案 1 :(得分:1)
这不是回答问题,而是测试参数的长度,而不是模式匹配它并返回正确的内容
main = do
let (opt, contentM) = case getArgs of
[opt] -> (op, getContent)
[opt, file] -> (op, hGetContent file)
_ -> error ("Invalid count of argument")
inGramma <- fmap getGramma contentM
doJob opt inGramma