从单子转化为应用性(Translate from monad to applicative)

2019-08-17 05:10发布

好了,我知道什么是Applicative型类包含的,为什么这是有用的。 但我不能完全环绕你如何使用它在非简单的例子,我的大脑。

举个例子,下面很简单秒差距解析器:

integer :: Parser Integer
integer = do
  many1 space
  ds <- many1 digit
  return $ read ds

现在,如何赫克你会写,如果没有使用Monad实例Parser ? 很多人声称,这是可以做到,是一个不错的主意,但我无法弄清楚究竟是如何。

Answer 1:

integer :: Parser Integer
integer = read <$> (many1 space *> many1 digit)

要么

integer = const read <$> many1 space <*> many1 digit

不管你认为其中任一更易读是你。



Answer 2:

我会写

integer :: Parser Integer
integer = read <$ many1 space <*> many1 digit

有一堆左结合(如应用程序)语法分析器建设运营的<$> <*> <$ <* 在最左边的事应是纯功能是组装从元件值的结果值。 每个运营商右边的东西应该是一个分析器,集体给左到右的语法成分。 其中运营商使用取决于两种选择,如下所示。

  the thing to the right is    signal  / noise
  _________________________            
  the thing to the left is \           
                            +-------------------
                    pure /  |   <$>       <$
                  a parser  |   <*>       <*

所以,具有选择read :: String -> Integer作为将要递送解析器的语义的纯函数,我们可以前导间隔作为“噪声”和数字作为“信号”的一群进行分类,因此

 read <$ many1 space <*> many1 digit
 (..)    (.........)     (.........)
 pure    noise parser     |
 (.................)      |
     parser              signal parser
 (.................................)
                    parser

您可以结合使用多种可能性

p1 <|> ... <|> pn

并表示与不可能

empty

这是很少有必要在解析器名称组件,并将得到的代码看起来更像是附加了语义语法。



Answer 3:

您的例子可以逐步改写到更清晰类似于一个应用型的一种形式:

do
  many1 space
  ds <- many1 digit
  return $ read ds
  1. 定义do记号:

     many1 space >> (many1 digit >>= \ds -> return $ read ds) 
  2. 的定义$

     many1 space >> (many1 digit >>= \ds -> return (read ds)) 
  3. 的定义.

     many1 space >> (many1 digit >>= (return . read)) 
  4. 第三个单子法(关联性):

     (many1 space >> many1 digit) >>= (return . read) 
  5. 的定义liftM (在非do记号):

     liftM read (many1 space >> many1 digit) 

这是(或者应该是,如果我没有搞砸了:))的行为,你的例子是相同的。

现在,如果你更换liftMfmap<$>>>*>你会得到应用型:

read <$> (many1 space *> many1 digit)

这是有效的,因为liftMfmap<$>一般应该是同义词,因为都是>>*>

这一切工作,我们可以做到这一点,因为原来的例子没有使用任何解析器的结果,建立一个下解析器。



文章来源: Translate from monad to applicative