在字符串列表中对字符串使用Maybe

时间:2019-03-24 15:27:54

标签: haskell

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

我的问题是我通常会使用递归在列表中找到String,然后返回所有内容;但是,我是Maybe语句的新手,所以我不确定递归是否是检查并返回所需内容的最佳方法。

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

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

1 个答案:

答案 0 :(得分:4)

就像@RobinZigmond所说的那样,递归在这里可以正常工作,并且对Maybe值使用递归没有什么特别的。不要将NothingJust视为“声明”。 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总是会成功。 (对于用户定义的数据类型,从技术上讲,这可能是错误的。)