#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. Просто очевидный, а именно, что это две разные строки; Я просто хотел дать этой версии новое имя.