【问题标题】:Finding the index of a string that contains a substring recursively递归查找包含子字符串的字符串的索引
【发布时间】:2019-04-22 15:14:43
【问题描述】:

我试图在包含某个子字符串的列表的上下文中查找字符串的索引,但无济于事。我不确定如何将整个未触及的数组作为参数传递给递归函数中的另一个函数。这是我的方法:

find' :: [String] -> Maybe Int
find' [] = error "List is empty"
find' [x] = return maybe 0
find' (x:xs)
    | "HU" `isInfixOf` x = return elemIndex x (x:xs)
    | otherwise = checkTail
    where checkTail = find' xs

错误是:

 * Couldn't match type `[[String]] -> Maybe Int' with `Maybe Int'
  Expected type: String -> [String] -> Maybe Int
    Actual type: String -> [String] -> [[String]] -> Maybe Int
* The function `return' is applied to three arguments,
  but its type `([String] -> [[String]] -> Maybe Int)
                -> String -> [String] -> [[String]] -> Maybe Int'
  has only four
  In the expression: return elemIndex x (x : xs)
  In an equation for find':
      find' (x : xs)
        | "HU" `isInfixOf` x = return elemIndex x (x : xs)
        | otherwise = checkTail
        where
            checkTail = find' xs

   | "HU" `isInfixOf` x = return elemIndex x (x:xs)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^

我真的不明白错误以及为什么它不匹配,因为在这两种情况下我都返回一个可能的 int。但是,正如我所提到的,我不确定 (x:xs) 是否实际上意味着参数的整个列表。 澄清一下,我试图从字符串列表中找到字符串的索引。

【问题讨论】:

  • 我发现很难理解你想用这个做什么 - 特别是你所说的 returnmaybe 是什么意思。它们都是 Haskell 中的标准函数,但我强烈怀疑两者都不是你认为的那样。 (特别是return maybe 0认为你的意思是Just 0

标签: haskell recursion


【解决方案1】:

首先,maybe 本身就是一个函数;它的作用与问题无关。可以这么说,return 0 做你想做的事:它从函数返回 Just 0

find' :: [String] -> Maybe Int
find' [] = Nothing
find' [x] = return 0 -- equivalent to find' [x] = Just 0

(注意Nothing的使用;如果你要引发错误,没有理由使用Maybe Int而不是Int作为返回类型。另外,没有理由使用return Just,因为您不是在这里尝试支持任意 monad。)

此外,elemIndex已经返回一个Maybe Int类型的值;您不需要使用 return 函数,该函数将值包装在另一层中,生成 Maybe (Maybe Int) 值,这不是您想要的。

find' (x:xs)
    | "HU" `isInfixOf` x = elemIndex x (x:xs)
    | otherwise = find' xs

最后一个问题:如果"HU" 不存在于列表的第一个元素中,则只需在列表的尾部调用find' 是正确的。但是,您需要将 1 添加到该返回值以补偿传递较短的参数。 (这也意味着您不需要elemIndex,因为您总是在当前列表的头部找到"HU"。)

find' (x:xs)
    | "HU" `inInfixOf` x = Just 0
    | otherwise = fmap (1+) (find' xs)

你需要使用fmap; find' 返回 Maybe Int,而不是 Int,因此 1 + find' xs 本身不起作用。

这也意味着您可以删除 [x] 的特殊情况,因为它是在列表头部找到搜索字符串之后得出的。整个函数只是

find' :: [String] -> Maybe Int
find' [] = Nothing
find' (x:xs)
    | "HU" `isInfixOf` x = Just 0
    | otherwise = fmap (1+) (find' xs)

处理整个列表的一种方法是一次搜索整个列表,然后在结果布尔值列表中找到(第一次)出现的 True。

find'' :: [String] -> Maybe Int
find'' xs = elemIndex True (map ("HU" `inInfixOf`) xs)
-- or find'' = elemIndex True . map ("HU" `inInfixOf`)
-- or find'' = findIndex ("HU" `inInfixOf`)

【讨论】:

  • 感谢您的回答,但是问题不是要在字符串中查找子字符串的索引,而是要在该列表元素中存在子字符串时查找字符串项的索引。通过去掉不必要的返回并在第一个有效情况下使用 Just 0,它现在可以正确编译,但实际上并没有在列表中找到合适的字符串。这就是为什么我试图使用整个列表而不考虑 elemIndex 函数的递归状态,因为我想知道整个列表上下文中字符串的索引。但我仍然对那部分一无所知。
  • 哦!抱歉,我把[String]String 混为一谈了。
  • 您能建议我如何为此更改递归部分吗?无论我尝试哪个列表,答案都是 0 或无,即使“HU”确实出现在索引 6 中。真的很生气,因为在我看来,在这个阶段它非常有意义
  • 查看我的更新;您根本不需要elemIndex,因为您查看(或找到)字符串"HU" 的唯一位置是在列表的头部。当您致电inFixOf 时,已经没有“完整”列表可供查看;您只有当前呼叫收到的列表。也就是说,您还可以设计一个确实使用elemIndex的定义。
  • 只是显而易见的,即它们是两个不同的字符串;我只是想给那个版本一个新名字。
猜你喜欢
  • 2016-05-20
  • 2014-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多