Haskell 分析器的函子
作为家庭作业的一部分,我们正在Haskell中研究解析器。我们有这种数据类型Haskell 分析器的函子,haskell,functor,Haskell,Functor,作为家庭作业的一部分,我们正在Haskell中研究解析器。我们有这种数据类型 newtype Parser a = Parser { parse :: String -> Maybe (a,String) } 这对我来说很清楚,我们的解析器得到的字符串是类型a的返回表达式和剩余的未解析字符串 但接下来我们要做的是函子定义: instance Functor Parser where fmap f p = Parser $ \s -> (\(a,c) ->
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
实例函子解析器,其中
fmap fp=Parser$\s->(\(a,c)->(fa,c))parse ps
我完全迷路了。在我看来,parse p s给出了从类型a解析的表达式,但我无法理解这个fmap实际上在做什么,以及为什么它有意义
希望有人能给我一个线索
谢谢 给定一个解析器
p
,fmap fn p
将创建一个新的解析器,解析与p
相同的文本,然后将fn
应用于输出。例如,如果您有一个解析器parseOptionalNumber::parser(可能是Int)
,您可以通过从just parseOptionalNumber执行parseNumber=fmap将其转换为parseNumber::parser Int
(尽管您不想这样做,因为just
是部分的)
至于实现,它的工作原理如下:
- 整个过程被包装在
中,它创建了一个新的解析器,在给定输入字符串Parser$\s->…
的情况下执行s
…
使用函数parse p s
(根据parse::Parser a->(String->Maybe(a,String))
的定义)在输入字符串Parser a
上运行输入解析器s
,生成类型为p
的输出Maybe(a,String)
是函数()
的同义词,但作为运算符而不是函数。它将左侧的函数映射到右侧的fmap
输出。它映射的函数是Maybe(a,String)
,它在给定解析器\(a,c)->(fa,c)
的输出p
上运行给定函数(a,c)
f
fmap
更有用:
实例函子解析器,其中
fmap f inParser=Parser$\inputStr->
的案例(parse inParser inputStr)
无->无
Just(result,leftoverString)->Just(f result,leftoverString)
给定一个解析器p
,fmap fn p
将创建一个新的解析器,该解析器解析与p
相同的文本,但随后将fn
应用于输出。例如,如果您有一个解析器parseOptionalNumber::parser(可能是Int)
,您可以通过从just parseOptionalNumber
执行parseNumber=fmap将其转换为parseNumber::parser Int
(尽管您不想这样做,因为just
是部分的)
至于实现,它的工作原理如下:
- 整个过程被包装在
Parser$\s->…
中,它创建了一个新的解析器,在给定输入字符串s
的情况下执行…
parse p s
使用函数parse::Parser a->(String->Maybe(a,String))
(根据Parser a
的定义)在输入字符串s
上运行输入解析器p
,生成类型为Maybe(a,String)
的输出
()
是函数fmap
的同义词,但作为运算符而不是函数。它将左侧的函数映射到右侧的Maybe(a,String)
输出。它映射的函数是\(a,c)->(fa,c)
,它在给定解析器p
的输出(a,c)
上运行给定函数f
希望这是有意义的;如果没有,您可能会发现以不太紧凑的形式重写fmap
更有用:
实例函子解析器,其中
fmap f inParser=Parser$\inputStr->
的案例(parse inParser inputStr)
无->无
Just(result,leftoverString)->Just(f result,leftoverString)
有一件事让定义变得更加混乱,那就是元组将结果存储在第一个位置。如果是第二个,那么您可以使用元组本身的函子实例来获取fmap f p=Parser$\s->fmap f parse p s
(也就是说,
挖掘Maybe
值,然后fmap
挖掘元组。)有一件事使得定义比它需要的更令人困惑,那就是元组将结果存储在第一个位置。如果是第二个,那么您可以使用元组本身的函子实例,以获得fmap f p=Parser$\s->fmap f parse p s
(即,
挖掘Maybe
值,并且fmap
挖掘元组。)(旁注)即fmap fp=Parser(\s->do{(r,q)[(fr,q)|(r,q)(旁注),即…fmap fp=Parser(\s->do{(r,q)[(fr,q)|(r,q)