如何实现Haskell递归函数readUntil:读取用户输入至满足条件
完善Haskell的
readUntil递归实现 我来帮你搞定这个递归版的readUntil函数~先看看你原代码里的小问题,再给出两种可行的实现方案:
首先,你的核心思路是对的——用辅助递归函数累积输入行,直到触发停止条件。不过原代码里有个明显的语法错误:if f = True这部分不对,因为f是String -> Bool类型的函数,你需要把当前读取的行x传进去,写成if f x才行。
高效版实现(推荐)
这个版本用:把新行加到列表头部,最后反转得到正确的输入顺序,效率更高(因为:是O(1)操作,最后一次reverse是O(n),整体复杂度更优):
readUntil :: (String -> Bool) -> IO [String] readUntil f = go [] where go accumulated = do currentLine <- getLine if f currentLine then return (reverse accumulated) -- 反转后返回正确顺序的已读行 else go (currentLine : accumulated) -- 把当前行加入累积列表,继续递归
直观版实现(适合理解)
如果觉得反转的逻辑有点绕,也可以每次把新行追加到列表尾部,虽然效率稍低(++是O(n)操作),但递归流程更直观:
readUntil :: (String -> Bool) -> IO [String] readUntil f = go [] where go accumulated = do currentLine <- getLine if f currentLine then return accumulated -- 直接返回已累积的行 else go (accumulated ++ [currentLine]) -- 追加当前行后继续递归
逻辑说明
不管哪种版本,核心的递归逻辑都是一致的:
- 辅助函数
go负责累积已经读取的行,参数accumulated就是当前的累积列表 - 每次调用
getLine读取用户输入的一行 - 用判定函数
f检查当前行:如果返回True,就停止递归,返回累积的行列表;否则把当前行加入累积列表,继续递归调用go
内容的提问来源于stack exchange,提问作者Aelin
相关产品推荐
相关产品推荐

