Ваше решение работает с fmap
экземпляром Maybe
и я думаю, вы понимаете, это правильно?
Второй трудно получить, да - так, может быть, стоит вновь ввести некоторые точки и (
.. )
?
Сначала давайте добавить подпись к inParser
:
inParser :: ((String -> Maybe (a, String)) ->
(String -> Maybe(b, String)))
-> Parser a -> Parser b
, как вы можете видеть это на самом деле просто разворачивает/обертывания ядро проблемы;) - с помощью этого вы можете сосредоточиться на работе только с String -> Maybe (a,String)
другие части (fmap
, first
) есть по той же причине: они разворачивать вещи, пока вы можете получить в a
действовать на него:
fmap :: (a -> b) -> Parser a -> Parser b
fmap f p
{ def }
= inParser (fmap . fmap $ first f) $ p
{ def inParser }
= Parser . (fmap . fmap $ first f) . runParser $ p
запомнить runParser p
принимает String
и возвращает Maybe (a, String)
first f
является (a,c) -> (b,c)
или здесь (a,String) -> (b,String)
и первый fmap
есть используя экземпляр Maybe
-функтор, чтобы перевести это в Maybe (a,String) -> Maybe (b,String)
.
следующий fmap
переведет String -> Maybe (a, String)
в String -> Maybe (b, String)
, используя функтор-экземпляр (->) String
.
И наконец Parser
просто обертывает его снова.
Надеюсь, это немного поможет.
сказав, что ваша версия возможно более читаемым и в то время как второй один хороший мозг тизер и, кажется, более лаконична/Haskelly Я предпочел бы первый вариант;)