Haskell交互功能

时间:2013-05-28 19:19:44

标签: 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

它运行正常并按预期打印大写的参数 - 所以第一个函数出了什么问题?

2 个答案:

答案 0 :(得分:41)

interact :: String -> String获取包含 all 输入的字符串,并返回包含 all 输出的字符串。使用interact (map toUpper)按Enter后看到输出的原因是因为map toUpper懒惰地行动 - 它可以在知道所有输入之前开始提供输出。查找字符串的长度不是这样的 - 在生成任何输出之前必须知道整个字符串。

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

interact (unlines . map (show . length) . lines)

在每一行中总是很懒,所以你知道在每次输入后你都可以获得一个输出。

由于对行进行操作是如此常见的模式,我喜欢定义一个小辅助函数:

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

然后你可以这样做:

main = interact (eachLine inputLength)

答案 1 :(得分:0)

更可重用的解决方案:

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 ++ ">"