Мне трудно понять, как работает следующий код.Я пытаюсь следовать найденному примеру парсера здесь .Я использовал ReadP
раньше и хочу получить более глубокое понимание того, как работают парсеры.Мой вопрос не относится к парсерам, а скорее к тому, как работает функциональное приложение в Haskell.Вот код:
module NanoParsec where
import Data.Char
import Control.Monad
import Control.Applicative
newtype Parser a = Parser { parse :: String -> [(a,String)] }
runParser :: Parser a -> String -> a
runParser m s =
case parse m s of
[(res, [])] -> res
[(_, rs)] -> error "Parser did not consume entire stream."
_ -> error "Parser error."
item :: Parser Char
item = Parser $ \s ->
case s of
[] -> []
(c:cs) -> [(c,cs)]
Я понимаю, что импорт пока не нужен.Когда я загружаю это в ghci
, оно работает как положено:
Prelude> runParser item "m"
'm'
Prelude> runParser item "ms"
*** Exception: Parser did not consume entire stream.
Так что здесь нет ничего удивительного.У меня проблемы с тем, чтобы обернуть голову, как runParser
применяется к item
.Частичное применение runParser
к item
дает функцию типа String -> Char
:
Parser> :t runParser item
runParser item :: String -> Char
Вот как я пытаюсь десагар / применить runParser
к item
вручную:
runParser item
runParser Parser (\s -> ...)
(\m -> \s -> case parse m s of ...) Parser (\s -> ...)
Вот где я застрял.Если я заменю m
на функцию в Parser
, я получу parse parse s
, что мне кажется неправильным.Как мне применить runParser
к item
, чтобы я получил функцию типа String -> Char
?Я чувствую, что моя попытка обесценивания выключена.
РЕДАКТИРОВАТЬ : я ошибочно заявил, что item
применяется к runParser
;Я перепутал функцию и переменную здесь.