【问题标题】:Haskell interact functionHaskell 交互函数
【发布时间】:2013-05-28 19:19:43
【问题描述】:

我是 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

它运行正常并按预期以大写形式打印参数 - 那么第一个函数有什么问题?

【问题讨论】:

  • 我认为interact 仍然是编写与管道一起工作的命令行程序的好方法。有了IO,我很想编写不可组合的用户专用程序。

标签: haskell


【解决方案1】:

interactString -> String 参数应该接受一个包含all 输入的字符串,并返回一个包含all 输出的字符串。使用interact (map toUpper) 按回车后看到输出的原因是因为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)

【讨论】:

  • 对于我们新手,我会补充一点:inputLength = show . length
【解决方案2】:

更可重用的解决方案:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 2015-04-10
    • 2014-07-09
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    相关资源
    最近更新 更多