Haskell交互功能



我是Haskell的新手,有interact函数的问题。这是我的示例程序:

main :: IO ()
main = interact inputLength
inputLength :: String -> String
inputLength input = show $ length input

它编译,但是运行时不打印输出-只打印传递给它的字符串并移动到下一行。当我传递interact时,另一个String -> String函数如下所示:

upperCase :: String -> String
upperCase input = map toUpper input

可以正常运行,并按预期打印大写参数——那么第一个函数有什么问题呢?

interactString -> String参数应该接受包含所有输入的字符串,并返回包含所有输出的字符串。您在使用interact (map toUpper)按下enter键后看到输出的原因是map toUpper的行为是惰性的——它可以在所有输入都已知之前就开始输出。查找字符串的长度不是这样的——在产生任何输出之前必须知道整个字符串。

您需要发出EOF信号来表示您已经完成输入(在控制台中,这是Unix/Mac系统上的Control-D,我相信它是Windows上的Control-Z),然后它会给您长度。或者,您可以这样来查找每行的长度:

interact (unlines . map inputLength . lines)

这将在每行中始终是惰性的,因此您知道在每个输入之后可以得到一个输出。

由于行操作是一种常见的模式,所以我喜欢定义一个小的辅助函数:

eachLine :: (String -> String) -> (String -> String)
eachLine f = unlines . map f . lines

那么你可以这样做:

main = interact (eachLine inputLength)

更可重用的解决方案:

main = interactLineByLine processLine
-- this wrapper does the boring thing of mapping, unlining etc.... you have to do all the times for user interaction
interactLineByLine:: (String -> String) -> IO ()
interactLineByLine f = interact (unlines . (map processLine) . lines) 
-- this function does the actual work line by line, i.e. what is
-- really desired most of the times
processLine:: String -> String
processLine line = "<" ++ line ++ ">"

最新更新