我是一名哈斯克尔初学者。我的代码:
module Main (main) where
import System.IO
--Type for identifying Students.
data Student = Student {
name :: String,
regnum :: Integer
} deriving (Show, Read)
getData :: IO (String)
getData = do
putStr "\tEnter the student's name: "
name <- getLine
putStr "\tEnter the registration number: "
regstr <- getLine
let regno = (read regstr) :: Integer
return (show ( Student name regno ))
addData :: String -> IO (Bool)
addData filename = do
fileData <- getData
appendFile filename fileData
return True
printData :: String -> IO (Bool)
printData filename = do
fileData <- readFile filename
putStrLn fileData
return True
resetFile :: String -> IO (Bool)
resetFile filename = writeFile filename "" >> return True
action :: Char -> String -> IO (Bool)
action option filename =
if option == '1'
then addData filename
else if option == '2'
then printData filename
else if option == '3'
then resetFile filename
else return False
main = do
putStr "What do you want to do?\n\t1) Add a new record to a file.\n\t2) Read a record from a file.\n\t3) Reset the file.\n>> "
option <- getChar
action option "records.txt"
我得到的输出是:
What do you want to do?
1) Add a new record to a file.
2) Read a record from a file.
3) Reset the file.
>> 1
Enter the student's name: Enter the registration number:
因此我无法为学生的姓名提供输入。我在 ghci 上运行代码。当我试图看它如何作为可执行文件运行时,它给出了更奇怪的输出。
What do you want to do?
1) Add a new record to a file.
2) Read a record from a file.
3) Reset the file.
(请注意,它不会打印“&gt;&gt;”)。只有在我按两次Enter后才打印“&gt;&gt;”。 我无法理解这里发生了什么。我的代码的其他改进非常受欢迎。
编辑::通过使用getLine而不是getChar,该程序适用于ghci(感谢Daniel Fischer)。但是在编译时它仍然不起作用。新输出是:
What do you want to do?
1) Add a new record to a file.
2) Read a record from a file.
3) Reset the file.
1 (Typed my me)
Tom (Typed my me)
234 (Typed my me)
>> Enter the student's name: Enter the registration number:
重新运行以读取文件:
What do you want to do?
1) Add a new record to a file.
2) Read a record from a file.
3) Reset the file.
2 (Typed my me)
>> Student {name = "Tom", regnum = 234}
为什么“&gt;&gt;”并且在获取输入后打印getData的putStr
?
答案 0 :(得分:4)
option <- getChar
使用默认缓冲设置,程序仅在输入换行符后才接收输入。但是,getChar
仅删除从输入缓冲区输入的第一个字符,因此以下getLine
从输入缓冲区中读取,直到找到换行符。在你的情况下,立即开始。
你可以(至少在* nix-ish系统上,缓冲控制用于在Windows上无法正常工作,我不知道它现在是否可以)通过关闭stdin
的缓冲来解决问题,< / p>
main = do
hSetBuffering stdin NoBuffering
...
所以getChar
收到输入而没有输入换行符。或者,不要使用getChar
作为选项,而是使用
(option:_) <- getLine
因此输入缓冲区中没有任何内容可以自动满足以下getLine
。
此外,要在输入输入之前输出提示,请致电
hFlush stdout
刷新输出缓冲区,或关闭stdout
的缓冲。
最简单的可能是定义
prompt :: String -> IO ()
prompt msg = do
putStr msg
hFlush stdout
并通过调用putStr
替换对prompt
的来电。
对编码风格的批判:
getData :: IO (String)
将IO
类型构造函数的参数括在括号中。这不是必要和单一的。写它的正常方法是IO String
。 (你可能在某处看到IO ()
的括号,但那些不是括号的括号,那是()
类型的类型构造函数。令人困惑?是的。)
action :: Char -> String -> IO (Bool)
action option filename =
if option == '1'
then addData filename
else if option == '2'
then printData filename
else if option == '3'
then resetFile filename
else return False
应该成为case
,
action option filename
= case option of
'1' -> addData filename
'2' -> printData filename
'3' -> resetFile filename
_ -> return False
除此之外,代码看起来很干净。