作为家庭作业的一部分,我们正在Haskell中研究解析器。我们有此数据类型
newtype Parser a = Parser { parse :: String -> Maybe (a,String) }
这对我来说很清楚,我们的解析器获取的字符串是类型a的返回表达式以及其余未解析的字符串。
但是接下来我们有这个函子定义:
instance Functor Parser where
fmap f p = Parser $ \s -> (\(a,c) -> (f a, c)) <$> parse p s
而我完全迷路了。在我看来,parse p s给出了类型a的解析表达式,但我无法理解此fmap实际在做什么以及为什么有意义。
希望有人可以给我一个线索。
谢谢!
给出解析器p
,fmap fn p
将创建一个新的解析器,该解析器解析与p
相同的文本,然后将fn
应用于输出。例如,如果您有一个解析器parseOptionalNumber :: Parser (Maybe Int)
,则可以通过执行parseNumber :: Parser Int
将其转换为parseNumber = fmap fromJust parseOptionalNumber
(尽管您不想这样做,因为fromJust
是部分的)。
至于实现,它是这样的:
Parser $ \s -> …
中,这创建了一个新的解析器,该解析器在给定输入字符串…
的情况下执行s
。parse p s
使用函数parse :: Parser a -> (String -> Maybe (a,String))
(来自Parser a
的定义)对输入字符串p
运行输入解析器s
,产生类型为Maybe (a,String)
的输出。(<$>)
是函数fmap
的同义词,但作为运算符而不是函数。它将左侧的功能映射到右侧的Maybe (a,String)
输出。它映射的函数为\(a,c) -> (f a, c)
,它将在给定解析器f
的输出(a,c)
上运行给定函数p
。希望这很有道理;如果不是这样,您可能会发现以不太紧凑的格式重写fmap
更有用:
instance Functor Parser where
fmap f inParser = Parser $ \inputStr ->
case (parse inParser inputStr) of
Nothing -> Nothing
Just (result, leftoverString) -> Just (f result, leftoverString)