Parsing Haskell中带do构造的简单解析
我正在尝试编写一个简单的解析器,因此所有声明都列在下图中,但是当我尝试编译这个模块时,它失败了。 我正在遵循此来源提供的教程-> 特别是Erik Meijer博士的这段视频() 问题是,我认为“do”构造能够以降序方式“串联”来自前一个函数的输出,但这个p函数的工作方式对我来说似乎很神奇。什么是正确的实现Parsing Haskell中带do构造的简单解析,parsing,haskell,functional-programming,Parsing,Haskell,Functional Programming,我正在尝试编写一个简单的解析器,因此所有声明都列在下图中,但是当我尝试编译这个模块时,它失败了。 我正在遵循此来源提供的教程-> 特别是Erik Meijer博士的这段视频() 问题是,我认为“do”构造能够以降序方式“串联”来自前一个函数的输出,但这个p函数的工作方式对我来说似乎很神奇。什么是正确的实现 -- Generic Parser. type Parser a = String -> [(a, String)] -- A simple Parser that captures
-- Generic Parser.
type Parser a = String -> [(a, String)]
-- A simple Parser that captures the first char of the string, puts it in
-- the first position of the couple and then puts the rest of the string into
-- the second place of the couple inside the singleton list.
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x, xs)]
-- Simple parser that always fails.
failure :: Parser a
failure = \inp -> []
-- Returns the type of the parser without operating on the input.
return1 :: a -> Parser a
return1 v = \inp -> [(v, inp)]
-- Explicit call to parse.
parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp
-- Some kind of "or" operator that if the first parser fails (returning an empty list) it
-- parses the second parser.
(+++) :: Parser a -> Parser a -> Parser a
p +++ q = \inp -> case p inp of
[] -> parse q inp
[(v, out)] -> [(v, out)]
-- The function within I'm having troubles.
p :: Parser (Char,Char)
p = do
x <- item
item
y <- item
return1 (x, y)
——泛型解析器。
类型解析器a=String->[(a,String)]
--一个简单的解析器捕获字符串的第一个字符,并将其放入
--第一个位置的夫妇,然后把其余的字符串进入
--这对夫妇在独生子女名单中的第二名。
项::解析器字符
item=\inp->case inp of
[] -> []
(x:xs)->[(x,xs)]
--总是失败的简单解析器。
失败::分析器a
失败=\inp->[]
--返回解析器的类型,而不对输入进行操作。
return1::a->Parser a
return1 v=\inp->[(v,inp)]
--显式调用解析。
parse::Parser a->String->[(a,String)]
解析p inp=p inp
--某种类型的“或”运算符,如果第一个解析器失败(返回空列表),它将
--解析第二个解析器。
(+++)::解析器a->解析器a->解析器a
p+++q=\inp->
[]->parse q inp
[(v,out)]->[(v,out)]
--我内心的功能有问题。
解析器(Char,Char)
p=do
x您的解析器
只是函数的类型同义词。您所看到的友好解析器都是自己的适当类型,带有Functor
和Applicative
实例,以及(在大多数情况下)Alternative
、Monad
和MonadPlus
实例。您可能需要类似以下(未经测试,从未编译)版本的内容
import Control.Monad(ap,liftM)
进口控制。适用(可选(..)
newtype解析器a=解析器
{runParser::String->[(a,String)]}
实例函子解析器,其中
fmap=liftM
实例应用程序解析器,其中
纯v=解析器$\inp->[(v,inp)]
()=ap
实例Monad解析器,其中
--不需要下一行
--GHC最新版本
--返回=纯
解析器m>>=f=Parser$\s->
[(r,s'')|(x,s')您的解析器
只是函数的类型同义词。您所看到的友好解析器都是它们自己的适当类型,带有Functor
和Applicative
实例,以及(在大多数情况下)Alternative
、Monad
和MonadPlus
实例。您可能需要类似以下(未测试,从未编译)版本的内容
import Control.Monad(ap,liftM)
进口控制。适用(可选(..)
newtype解析器a=解析器
{runParser::String->[(a,String)]}
实例函子解析器,其中
fmap=liftM
实例应用程序解析器,其中
纯v=解析器$\inp->[(v,inp)]
()=ap
实例Monad解析器,其中
--不需要下一行
--GHC最新版本
--返回=纯
解析器m>>=f=Parser$\s->
[(r,s'')|(x,s')您的解析器的Monad
实例在哪里?您的p
正在使用(>)String
monad,不是任何类型的Parser
monad。你需要将Parser
anewtype
,然后为它编写monad
实例,然后才能使用do
。@n.m.对不起,我编辑了这个问题。我不明白为什么会被否决。应该替换图像,我同意--但至少这个问题显示了一些努力,不像学习哈斯克尔的人所做的其他许多努力。我认为埃里克·梅杰在他的演讲中玩弄得又快又松。你不能真的用一元解析的方式将Parser
作为Monad
的一个实例。问题是,String->
是Monad(因此do表示法有效),但它是一个错误的实例,并且生成了所有错误的类型。请尝试使用显式的bind
而不是do
重写此函数。或者,您可以将Parser
包装成如下的新类型newtype Parser a=Parser{unparser::String->[(a,String)]
并为此定义一个Monad实例…但这对于第一节Monad课程来说可能太多了…您的解析器的Monad
实例在哪里?您的p
正在使用(>)String
monad,不是任何类型的Parser
monad。你需要将Parser
anewtype
,然后为它编写monad
实例,然后才能使用do
。@n.m.对不起,我编辑了这个问题。我不明白为什么会被否决。应该替换图像,我同意--但至少这个问题显示了一些努力,不像学习哈斯克尔的人所做的其他许多努力。我认为埃里克·梅杰在他的演讲中玩弄得又快又松。你不能真的用一元解析的方式将Parser
作为Monad
的一个实例。问题是,String->
是Monad(因此do表示法有效),但它是一个错误的实例,并且生成了所有错误的类型。请尝试使用显式的bind
而不是do
重写此函数。或者,您可以将Parser
包装成如下的新类型newtype Parser a=Parser{unparser::String->[(a,String)]
并为此定义一个Monad实例……但这对于第一节Monad课程来说可能太多了。。。
import Control.Monad (ap, liftM)
import Control.Applicative (Alternative (..))
newtype Parser a = Parser
{ runParser :: String -> [(a, String)] }
instance Functor Parser where
fmap = liftM
instance Applicative Parser where
pure v = Parser $ \inp -> [(v, inp)]
(<*>) = ap
instance Monad Parser where
-- The next line isn't required for
-- recent GHC versions
-- return = pure
Parser m >>= f = Parser $ \s ->
[(r, s'') | (x, s') <- m s
, (r, s'') <- runParser (f r) s']
(+++) :: Parser a -> Parser a -> Parser a
p +++ q = Parser $ \inp -> case runParser p inp of
[] -> runParser q inp
[(v, out)] -> [(v, out)]
failure :: Parser a
failure = Parser $ \inp -> []
instance Alternative Parser where
(<|>) = (+++)
empty = failure
instance MonadPlus Parser