Как [a]
является Monoid определить по,
instance Monoid [a] where
mempty = []
mappend = (++)
Затем Maybe [a]
также Monoid,
instance Monoid a => Monoid (Maybe a) where
mempty = Nothing
Nothing `mappend` m = m
m `mappend` Nothing = m
Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
Обратите внимание на тип ограничения в объявлении экземпляра, которые налагают a
быть Monoid или иначе Maybe a
не будет.
Затем мы можем использовать mappend, (<>)
, чтобы связать наш рекурсивный вызов при условии, чтобы преобразовать головку списка в одноэлементный.
import Data.Monoid ((<>))
myReverse :: [a] -> Maybe [a]
myReverse [] = Nothing
myReverse (x:xs) = myReverse xs <> Just [x]
Последнее замечание, предыдущее решение сложения также может быть улучшено.
>>> let mrev = foldl' (\x y -> Just [y] <> x) Nothing
>>> mrev []
Nothing
>>> mrev "hello"
Just "olleh"
Предыдущий ответ складка
Зная, что обратный можно определить с помощью складка, как следовать,
>>> foldl' (flip (:)) [] [1..5]
[5,4,3,2,1]
Это можно переписать в виде,
>>> foldl' (\x y -> y:x) [] [1..5]
[5,4,3,2,1]
Чтобы адаптироваться к Maybe типа, мы делаем следующее преобразование,
- Семя
[]
стать (Just [])
- Анонимная функция должна теперь быть применимы внутри Just, мы используем БПМЖ, чтобы сделать это.
Это приводит нас к,
>>> foldl' (\x y -> fmap (y:) x) (Just []) [1..5]
Just [5,4,3,2,1]
Наконец,
mreverse xs | null xs = Nothing
| foldl' (\x y -> fmap (y:) x) (Just []) xs
Просто из любопытства, почему вы не реализующий такое же поведение, что и оригинальный 'reverse' функции? Почему пустым списком не может быть пустой список? –
Да, это может быть, но цель состоит в том, чтобы узнать больше о Haskell (чтобы противостоять этой проблеме, вы должны попробовать множество решений и искать ответы, и поэтому вы узнаете новые вещи). – vildric