Рекурсивный поиск индекса строки, содержащей подстроку

#haskell #recursion

#haskell #рекурсия

Вопрос:

Я пытаюсь найти индекс строки в контексте списка, содержащего определенную подстроку, но безрезультатно. Я не уверен, как можно передать весь нетронутый массив в качестве аргумента другой функции в рекурсивной функции. Вот мой подход:

 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)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^
  

Я действительно не понимаю ошибку и почему она не совпадает, потому что в обоих случаях я возвращаю значение maybe int . Однако, как я уже упоминал, я не уверен, что (x: xs) на самом деле означает весь список для аргумента.
Просто чтобы уточнить, я пытаюсь найти индекс строки из списка строк.

Комментарии:

1. Мне очень трудно понять, что вы пытаетесь с этим сделать — в частности, что вы подразумеваете под return и maybe . Обе они являются стандартными функциями в Haskell, но я сильно подозреваю, что ни одна из них не делает того, что вы думаете. (В частности, return maybe 0 я думаю , вы просто имеете в виду Just 0 )

Ответ №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 over Just , поскольку вы не пытаетесь поддерживать здесь произвольную монаду.)

Кроме того, 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' возвращает a Maybe Int , а не an 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`)
  

Комментарии:

1. спасибо за ваш ответ, однако вопрос заключался не в том, чтобы найти индекс подстроки внутри строки, а в том, чтобы найти индекс элемента string, ЕСЛИ подстрока присутствует в этом элементе списка. убирая ненужные возвраты и используя только 0 в первом допустимом случае, теперь он компилируется должным образом, но на самом деле не находит подходящую строку в списке. вот почему я пытаюсь использовать весь список независимо от состояния рекурсии с помощью функции elemIndex, потому что я хочу знать индекс строки в контексте всего списка. но я все еще не знаю об этой части.

2. О! Извините, я мысленно слил [String] с String .

3. Не могли бы вы посоветовать, как я мог бы захотеть изменить рекурсивную часть для этого? Независимо от того, какой список я пробую, ответ либо просто 0, либо ничего, даже если ‘HU’ действительно присутствует в индексе 6. Действительно бесит, потому что в моей голове это имеет смысл на данном этапе

4. Смотрите мое обновление; вам вообще не нужно elemIndex , потому что единственное место, где вы смотрите (или находите) строку "HU" , находится в начале списка. К моменту вызова inFixOf «всего» списка для просмотра нет; у вас есть только список, полученный текущим вызовом. Тем не менее, вы также можете придумать определение, которое действительно использует elemIndex .

5. Просто очевидный, а именно, что это две разные строки; Я просто хотел дать этой версии новое имя.