首页 > 解决方案 > 对字符串列表中的字符串使用 Maybe

问题描述

我正在尝试检查字符串是否包含在字符串列表中,如果是,我想在找到字符串后返回列表中的其余字符串。

我的问题是我通常会使用递归在列表中查找字符串,然后返回所有内容;但是,我是 Maybe 语句的新手,所以我不确定递归是否是检查和返回我想要的内容的最佳方式。

strReturn :: String -> [String] -> Maybe [String] 
strReturn x (y : ys)
  | x == y = Just ys
  | x /= y = Nothing

我写的代码只检查列表的头部;我不确定如何在 Maybe 语句的语法中检查列表的其余部分 - 我想在字符串之后返回所有内容。这以所有正确的方式工作,但仅适用于头部。如果字符串在除了头部之外的任何地方,它不会看到它或返回任何东西。

标签: haskell

解决方案


Maybe正如@RobinZigmond 所说,递归在这里可以正常工作,并且将递归与值一起使用并没有什么特别之处。不要将NothingandJust视为“陈述”。 Nothing是一个值,并且Just ["a","b","c"]是一个值,并且返回此类值的递归函数的编写和使用方式与返回整数的递归函数大致相同。

以下剧透,但请先尝试自己动手,并提供进一步的提示。在您的定义中,Nothing是 type 的值Maybe [String]。您想将其替换为对 的递归调用strReturn,返回类型为strReturnis Maybe [String],这正是您需要的类型!不Just,是否需要“递归” - 只需尝试Nothing直接替换为类型检查的strReturn调用。

如果您仍然无法弄清楚,请继续阅读...

以您strReturn为起点,请注意,如果x /= y,那么您希望继续查看字符串的其余部分,因此这种情况应该是:

strReturn x (y : ys) | x /= y = strReturn x ys

这种类型检查很好。strReturn左边的调用需要返回一个 type 的值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。(对于用户定义的数据类型,这在技术上可能是错误的。)


推荐阅读