在Brent Yorgey的2013年UPenn class作业中,以下newtype
存在:
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
我正在尝试将Parser
实施为Functor
。
给出以下first
函数来帮助解决此问题:
first :: (a -> b) -> (a, c) -> (b, c)
first f (a, c) = (f a, c)
我尝试了以下内容:
instance Functor (Parser) where
fmap g (Parser f) = Parser $ fmap (first g) (f . g)
然而,这不起作用。
据我了解,f
的类型为String -> Maybe (a, String)
。所以,我不知道如何apply
String
到f
才能获得Maybe (a, String)
。
获得Maybe (a, String)
后,我相信我可以简单地运行fmap (first g) ...
,其中...
代表Maybe
。
请给我一个提示,了解如何获取Maybe (a, String)
。
由于f
欠String
来提供Maybe (a, String)
类型,我不知道在哪里找到String
参数。
答案 0 :(得分:6)
你做得很好。
如果我只是制作一个类型的同义词,那可能会更清楚
type M a = Maybe (a,String)
你可以使用
fmap (first g) :: Maybe (a, String) -> Maybe (b,String)
-- :: M a -> M b
并将其与
结合使用f :: String -> Maybe (a,String)
-- String -> M a
您只需要使用String -> M a
撰写M a -> M b
即可获得String -> M b
:
instance Functor (Parser) where
fmap g (Parser f) = Parser $ fmap (first g) . f
你问你是否可以从某个地方获得一个字符串。 Lambda将为您做到这一点:\xs ->
可以读作“给我一个字符串xs
...”,您可以将f
应用于该字符串以获得{{1}类型的内容}}。所以你也可以写:
Maybe (a,String)
答案 1 :(得分:0)
在分析器f上应用g,即复合g和f。但是,由于g是一般函数,并且f返回Maybe(a,String),我们需要将g转换为
Maybe(a,String)->d
。鉴于first::(a->b)->(a,c)->(b,c)
,然后
first.Maybe :: Maybe(a->b,a->b)->Maybe(a,String)->Maybe(b,String)
first.Maybe :: (a->b)->Maybe(a,String)->Maybe(b,String)
first.Maybe g :: Maybe(a,String)->Maybe(b,String)
所以
instance Functor Parser where
fmap g f = Parser $ fmap (first.Maybe g) . f