haskell - Haskell 如何终止递归调用并避免非穷举模式
问题描述
在基于终端的应用程序上工作,该应用程序使用多个putStr
/getLine
来收集用户输入。想使用以下函数putStr
getLine
通过向其提供问题列表并在列表中返回答案(递归)来缩短繁琐。尽管getLine
s 很好地终止了,但我无法避免事情non-exhaustive patterns
的putStr
一面。这不是重复的。可以使用多个getLine
来完成replicateM
,但它是我所追求的问题/答案的组合。
(***) = hFlush stdout
questionnaire :: [String] -> IO [String]
questionnaire (x:xs) = do
putStr x
(***)
user <- getLine
case user of
"" -> return []
_ -> do
nextUser <- questionnaire xs
return (user : nextUser)
解决方案
这里实际上不需要显式递归,因此不可能忘记定义questionaire
其参数何时为空列表。
questionaire :: [String] -> IO [String]
questionaire = traverse getWithPrompt
where getWithPrompt x = do
putStr x
(***)
getLine
例子:
> users <- questionaire ["name? ", "name? ", "name? "]
name? alice
name? bob
name? charlie
> users
["alice","bob","charlie"]
getWithPrompt
有类型String -> IO String
。traverse
有点像map
,除了 wheremap getWithPrompt prompts
会给你一个 type 的值[IO String]
,traverse
它将IO
动作列表组合成一个IO
动作,该动作执行每个IO
动作并将它们的结果收集到一个列表中。
正如 Daniel Wagner 所指出的,如果输入了空字符串,我忘记了停止。为了解决这个问题,我们可以回到你原来的递归,但要记住定义什么questionnaire []
意思。
questionnaire :: [String] -> IO [String]
questionnaire [] = return []
questionnaire (x:xs) = do
putStr x
(***)
user <- getLine
case user of
"" -> return []
_ -> do
nextUser <- questionnaire xs
return (user : nextUser)
推荐阅读
- sql - 从表中查找取消和替换匹配的最佳方法
- node.js - 如何将 Numeral.js 库放入 pug 文件 Node js 中?
- c# - 如何使用时间开始移动每个对象来轮流移动每个对象?
- java - 在 ImageJ 上编译插件过滤器时出错
- angular - (Angular)如何禁用组件模板中的“链接”标签?
- node.js - 使用 .HEIC 图像类型时,Google Vision OCR 无法检测到文本或图像
- flutter - 未处理的异常:类型 '_InternalLinkedHashMap
' 不是类型 'Map 的子类型 '在飞镖 - c++ - wcout 无法在 Windows 中从 wcin 打印 wstring
- c++ - 为什么指向基类的派生类指针可以调用派生类成员函数?
- arrays - 如何在C函数中将未知大小的矩阵作为参数传递?