我正在尝试检查字符串列表中是否包含字符串,如果是,我想在找到字符串后返回列表中的其余字符串。
我的问题是我通常会使用递归在列表中找到String,然后返回所有内容;但是,我是Maybe语句的新手,所以我不确定递归是否是检查并返回所需内容的最佳方法。
strReturn :: String -> [String] -> Maybe [String]
strReturn x (y : ys)
| x == y = Just ys
| x /= y = Nothing
我编写的代码仅检查列表的开头;我不确定如何在Maybe语句的语法内检查列表的其余部分-我想在字符串之后返回所有内容。这以所有正确的方式起作用,但仅适用于头部。如果String在头部之外的任何地方,它都不会看到或返回任何内容。
答案 0 :(得分:4)
就像@RobinZigmond所说的那样,递归在这里可以正常工作,并且对Maybe
值使用递归没有什么特别的。不要将Nothing
和Just
视为“声明”。 Nothing
是一个值,Just ["a","b","c"]
是一个值,并编写和使用返回此类值的递归函数,其方式与返回整数的递归函数相同。
以下扰流器,但请先尝试自己尝试,以进一步提示。在您的定义中,Nothing
是类型Maybe [String]
的值。您想用对strReturn
的递归调用来替换它,并且strReturn
的返回类型为Maybe [String]
,这正是您需要的类型!不需要Just
,也不需要“递归”,只需尝试用类型检查的Nothing
调用直接替换strReturn
。
如果仍然无法解决,请继续阅读...
以您的strReturn
为起点,请注意,如果x /= y
,则希望继续查找字符串的其余部分,因此这种情况应为:
strReturn x (y : ys) | x /= y = strReturn x ys
此类型检查正常。左侧的strReturn
调用需要返回类型为Maybe [String]
的值,幸运的是,右侧的递归strReturn
调用恰好具有该类型,所以没有问题。
现在代码的唯一问题是,如果找不到字符串,它将崩溃,因为最终您将用完字符串,并进行递归调用:
strReturn "whatever" []
与定义中的模式不匹配。您需要添加一个条件,说明如果到达列表的末尾(显然没有找到字符串,或者我们现在已经停止了),我们需要返回Nothing
:
strReturn _ [] = Nothing
完整的定义是:
strReturn :: String -> [String] -> Maybe [String]
strReturn _ [] = Nothing
strReturn x (y : ys)
| x == y = Just ys
| otherwise = strReturn x ys
请注意,使用otherwise
比使用x /= y
更好。这样既可以避免对编译后的代码进行不必要的检查,又可以避免在使用-Wall
进行编译(如果您要!)时会得到关于非穷尽模式的警告。编译器不够聪明,无法弄清楚如果x /= y
失败了,x == y
总是会成功。 (对于用户定义的数据类型,从技术上讲,这可能是错误的。)