当前位置: 首页 > 知识库问答 >
问题:

Haskell解析器、Monad和MonadPlus

燕禄
2023-03-14
    module Parser where

import           Control.Monad (MonadPlus, mplus, mzero)
import           Tagger        (Tag, Token)


newtype Parser a = Parser ([(Token, Tag)] -> [(a, [(Token, Tag)])])

parse :: Parser a -> [(Token, Tag)] -> [(a, [(Token, Tag)])]
parse (Parser p) = p

instance Functor Parser where
    fmap f p = do
        result <- p
        return (f result)

instance Monad Parser where
    return a = Parser (\cs -> [(a,cs)])
    p >>= f = Parser (\cs -> concat [parse (f a) cs' | (a,cs') <- parse p cs])

instance MonadPlus Parser where 
    p `mplus` q = Parser (\cs -> parse p cs ++ parse q cs)
    mzero = Parser (const [])

{-

这是我的解析器代码。显然,我已经用“旧的方式”做了,不能真正让它以新的方式工作。你能告诉我为了让它工作我需要修理哪些东西吗?我读了这篇文章(https://wiki.haskell.org/Functor-Applicative-Monad_Proposal)试图更改我的代码,但我觉得我做错了什么。

我得到的编译错误是:

Parser.hs:56:10:
    No instance for (Applicative Parser)
      arising from the superclasses of an instance declaration
    In the instance declaration for ‘Monad Parser’

Parser.hs:60:10:
    No instance for (GHC.Base.Alternative Parser)
      arising from the superclasses of an instance declaration
    In the instance declaration for ‘MonadPlus Parser’

编辑//

现在的代码是:

module Parser where

import           Control.Applicative
import           Control.Monad (mplus, mzero, liftM, ap)
import           Tagger        (Tag, Token)

-- type Token = String 
-- type Tag = String

newtype Parser a = Parser ([(Token, Tag)] -> [(a, [(Token, Tag)])])

parse :: Parser a -> [(Token, Tag)] -> [(a, [(Token, Tag)])]
parse (Parser p) = p

instance Functor Parser where
    fmap = liftM

instance Applicative Parser where
    pure a = Parser (\cs -> [(a,cs)])
    (<*>) = ap

instance Monad Parser where
    p >>= f = Parser (\cs -> concat [parse (f a) cs' | (a,cs') <- parse p cs])

instance MonadPlus Parser where --64
    p `mplus` q = Parser (\cs -> parse p cs ++ parse q cs)
    mzero = Parser (const [])

instance Alternative Parser where
    (<|>) = mplus
    empty = mzero

(+++) :: Parser a -> Parser a -> Parser a
p +++ q = Parser (\cs -> case parse (p `mplus` q) cs of
                           [] -> []
                           (x:_) -> [x])

错误:

Parser.hs:64:10:
Not in scope: type constructor or class ‘MonadPlus’

共有1个答案

陈允晨
2023-03-14

您可以遵循迁移指南。它简单明了:将return的定义移动到pure,添加

instance Functor Parser where
    fmap = liftM

instance Applicative Parser where
    pure a = Parser (\cs -> [(a,cs)])
    (<*>) = ap

instance Monad Parser where
    p >>= f = Parser (\cs -> concat [parse (f a) cs' | (a,cs') <- parse p cs])

对于Alternative来说,这只是样板文件,没有其他内容:

instance Alternative Parser where 
    (<|>) = mplus 
    empty = mzero

工作守则作为一个整体:

module Parser where

import           Control.Monad
import           Tagger        (Tag, Token)
import           Control.Applicative

newtype Parser a = Parser ([(Token, Tag)] -> [(a, [(Token, Tag)])])

parse :: Parser a -> [(Token, Tag)] -> [(a, [(Token, Tag)])]
parse (Parser p) = p

instance Functor Parser where
    fmap = liftM

instance Applicative Parser where
    pure a = Parser (\cs -> [(a,cs)])
    (<*>) = ap

instance Monad Parser where
    p >>= f = Parser (\cs -> concat [parse (f a) cs' | (a,cs') <- parse p cs])

instance MonadPlus Parser where
    p `mplus` q = Parser (\cs -> parse p cs ++ parse q cs)
    mzero = Parser (const [])

instance Alternative Parser where
    (<|>) = mplus
    empty = mzero

 类似资料:
  • 每当我键入print时,代码都是而不是从文件中看到的。 对这种行为有什么解决办法吗?

  • 动机: 避免样板代码 Monad提供了一种强大途径以构建带效果的计算。虽然各个标准monad皆专一于其特定的任务,但在实际代码中,我们常常想同时使用多种效果。 比如,回忆在第十章中开发的 Parse 类型。在介绍monad之时,我们提到这个类型其实是乔装过的 State monad。事实上我们的monad比标准的 State monad 更加复杂:它同时也使用了 Either 类型来表达解析过程中

  • 我对哈斯克尔有意见。我有这样的文本文件: 我不知道如何获得前两个数字(上面的2和7)和最后一行的列表。每行的末尾都有点。 我试图构建一个解析器,但名为readFile的函数返回名为IO String的Monad。我不知道如何从那种字符串中获取信息。 我更喜欢在一系列角色上工作。也许有一个函数可以将“IO字符串”转换为[Char]?

  • 问题内容: 我想在脚本中定义不同的子解析器,两个子解析器均从同一个父级继承选项,但具有不同的默认值。但是,它没有按预期工作。 这是我所做的: 当我从命令行运行脚本时,得到的是: 显然,第二个覆盖了父对象中的第一个。由于argparse文档中没有任何内容(非常详细),所以我认为这可能是一个错误。 有一些简单的解决方案吗?之后,我可以检查变量,并使用每个子解析器的预期默认值替换值,但这就是我期望arg

  • 问题内容: 可供选择(并坚持使用)的大量HTML解析器令人难以置信: http://java-source.net/open-source/html-parsers 如何选择最适合以下要求的产品: 成熟(错误比其他错误少) 生活和呼吸(即得到维持) 快速且资源高效(打算在Android上运行) 根据您的经验,您会推荐哪种HTML解析器(以满足上述要求),为什么? 问题答案: 好吧,我找到了答案,它

  • 我的问题是在遵循图片中的函数、应用程序和单子教程及其JavaScript版本时提出的。 当文本说functor从上下文中展开值时,我理解a- 我的问题是,整件拆开包装的事情有什么神奇之处?我的意思是,有一些自动打开“范围”变量的语言规则有什么问题?在我看来,这个操作只是某种表中的一个查找,其中符号对应于整数。 我的问题受到JavaScript版本的启发,其中是原型数组实例。所以展开确实不是火箭科学