解析器的函子
Functor for a parser
作为家庭作业的一部分,我们正在研究 Haskell 中的解析器。我们有这种数据类型
newtype Parser a = Parser { parse :: String -> Maybe (a,String) }
这对我来说很清楚,我们的解析器从类型 a 和剩余的未解析字符串中得到一个字符串是 return 表达式。
但是接下来我们要定义这个仿函数:
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 = fmap fromJust parseOptionalNumber
将它变成 parseNumber :: Parser Int
(尽管你不想这样做,因为 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
在给定解析器 p
. 的输出 (a,c)
上
希望这是有道理的;如果没有,您可能会发现以不太紧凑的形式重写 fmap
更有用:
instance Functor Parser where
fmap f inParser = Parser $ \inputStr ->
case (parse inParser inputStr) of
Nothing -> Nothing
Just (result, leftoverString) -> Just (f result, leftoverString)
作为家庭作业的一部分,我们正在研究 Haskell 中的解析器。我们有这种数据类型
newtype Parser a = Parser { parse :: String -> Maybe (a,String) }
这对我来说很清楚,我们的解析器从类型 a 和剩余的未解析字符串中得到一个字符串是 return 表达式。
但是接下来我们要定义这个仿函数:
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 = fmap fromJust parseOptionalNumber
将它变成 parseNumber :: Parser Int
(尽管你不想这样做,因为 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
在给定解析器p
. 的输出
…
(a,c)
上
希望这是有道理的;如果没有,您可能会发现以不太紧凑的形式重写 fmap
更有用:
instance Functor Parser where
fmap f inParser = Parser $ \inputStr ->
case (parse inParser inputStr) of
Nothing -> Nothing
Just (result, leftoverString) -> Just (f result, leftoverString)