#haskell #recursion
Вопрос:
Изучая Хаскелл, я наткнулся на эту функцию flipMaybe:
flipMaybe :: [Maybe a] -> Maybe [a]
flipMaybe [] = Just []
flipMaybe (Nothing:xs) = Nothing
flipMaybe (Just x:xs) = case flipMaybe xs of
Nothing -> Nothing
Just ls -> Just (x:ls)
Я не могу понять последнюю строчку. Что ls
здесь такое? Как здесь работает рекурсия? Или, другими словами, может ли кто-нибудь показать мне, как решает эта функция flipMaybe [Just 1, Just 2, Just 3]
? (шаг за шагом)
Комментарии:
1.
ls
являются ли данные, завернутые в aJust
рекурсии , поэтому , еслиflipMaybe [Just 2, Just 3]
это aJust
(здесьJust [2, 3]
, тоls
это список[2, 3]
, и это, таким образом, дополняетсяx
и завернуто в aJust
.2.
flipMaybe [Just 1, Just 2, Just 3]
—>case flipMaybe [Just 2, Just 3] of ...
—>case Just [2, 3] of Nothing -> Nothing; Just ls -> Just (1: ls)
—>Just (1:[2, 3])
3. Другими словами,
Just ls
вcase ... of ...
is сопоставление с образцом, аналогичное сопоставлению сJust x:xs
образцом в определенииfilpMaybe
. Но на этот раз вместо сопоставления шаблонов на входе функции мы выполняем сопоставление шаблонов на выходе рекурсивного вызоваflipMaybe xs
4. То, что вы здесь реализовали, является частным случаем
sequence
сm ~ Maybe
и.t ~ []
Ответ №1:
Я не могу понять последнюю строчку. Что
ls
здесь такое?
Если рекурсивный вызов в конце списка возвращает a Just ls
, то ls
это список, завернутый в Just
. Поэтому, если flipMaybe [Just 3]
вызывается, это вернет a Just [3]
, и, таким образом ls
, есть [3]
.
Это используется для добавления списка xs
. Если мы таким образом оцениваем flipMaybe [Just 1, Just 2]
, то сначала осматриваем первый пункт, если это а Nothing
, мы возвращаемся Nothing
: нас не волнует остальная часть списка, мы знаем , что результат будет а Nothing
, если это а Just …
, мы должны проверить, что flipMaybe [Just 2]
вернется. Если он возвращает a Nothing
, то мы , таким образом, возвращаемся Nothing
, так как тогда это означает, что Nothing
в конце списка есть a. Если это a Just ls
, то мы возвращаем a Just (x : ls)
, таким образом, мы добавляем элемент списка к результату рекурсивного вызова.
Если список таким образом выглядит [Just 2, Nothing, Just 3]
, то мы сначала исследуем Just 2
, так как это не Nothing
так , мы делаем рекурсивный вызов с. flipMaybe [Nothing, Just 3]
Так как этот список начинается с a Nothing
, Nothing
возвращается из flipMaybe [Nothing, Just 3]
, и, таким образом, мы возвращаемся Nothing
за flipMaybe [Just 2, Nothing, Just 3]
.