Parsing 应用解析器陷入无限循环

Parsing 应用解析器陷入无限循环,parsing,haskell,infinite-loop,lazy-evaluation,alternative-functor,Parsing,Haskell,Infinite Loop,Lazy Evaluation,Alternative Functor,我正在尝试实现自己的应用程序解析器,下面是我使用的代码: {-# LANGUAGE ApplicativeDo, LambdaCase #-} module Parser where -- Implementation of an Applicative Parser import Data.Char import Control.Applicative (some, many, empty, (<*>), (<$>), (<|>), Alternati

我正在尝试实现自己的应用程序解析器,下面是我使用的代码:

{-# LANGUAGE ApplicativeDo, LambdaCase #-}

module Parser where

-- Implementation of an Applicative Parser

import Data.Char
import Control.Applicative (some, many, empty, (<*>), (<$>), (<|>), Alternative)

data Parser a = Parser { runParser :: String -> [(a, String)] }

instance Functor Parser where
  -- fmap :: (a -> b) -> (Parser a -> Parser b)
  fmap f (Parser p) = Parser (\s -> [(f a, s') | (a,s') <- p s])

instance Applicative Parser where
  -- pure :: a -> Parser a
  -- <*> :: Parser (a -> b) -> Parser a -> Parser b
  pure x = Parser $ \s -> [(x, s)]
  (Parser pf) <*> (Parser p) = Parser $ \s -> 
               [(f a, s'') | (f, s') <- pf s, (a, s'') <- p s']

instance Alternative Parser where
  -- empty :: Parser a
  -- <|> :: Parser a -> Parser a -> Parser a
  empty = Parser $ \_s -> []
  (Parser p1) <|> (Parser p2) = Parser $ \s ->
      case p1 s of [] -> p2 s
                   xs -> xs

char :: Char -> Parser Char
char c = Parser $ \case (c':cs) | c == c' -> [(c,cs)] ; _ -> []

main = print $ runParser (some $ char 'A') "AAA"
{-#语言应用程序,LambdaCase}
模块解析器在哪里
--应用解析器的实现
导入数据.Char
import Control.Applicative(一些、许多、空、()、()、可选)
数据解析器a=解析器{runParser::String->[(a,String)]}
实例函子解析器,其中
--fmap::(a->b)->(解析器a->解析器b)
fmap f(Parser p)=解析器(\s->[(fa,s')|(a,s')解析器a
--::解析器(a->b)->解析器a->解析器b
纯x=解析器$\s->[(x,s)]
(解析器pf)(解析器p)=解析器$\s->
[(fa,s'')|(f,s')事实“星”:在您的
()
实现中:

…我们必须进行足够的计算,以知道这两个解析器实际上都是
解析器
构造函数对某个对象的应用,然后才能转到等号的右侧

事实“管道延迟”:在此实现中:

Parser p1 <|> Parser p2 = ...
p1 <|> p2 = Parser $ ...
让我们看一下您的第一个实现,我们知道“pipe strict”事实。我们想知道
some_v
是否是
解析器
对某事物的应用。由于事实“star”,因此我们必须知道
是否纯(:)
v
some_v纯[]
解析器对某事物的应用程序。要知道最后一个,我们必须知道
是否是某些
纯[]
Parser
对某物的应用。哎呀!我们刚刚演示了要知道
some\u v
是否是
Parser
对某物的应用,我们需要知道
some\u v
是否是
Parser
对某物的应用——一个无限循环

另一方面,在您的第二个实现中,为了检查
some_v
是否是
解析器
,我们仍然必须检查
pure(:)
v
,以及
some_v pure[]
,但由于“管道惰性”这一事实,这就是我们需要检查的全部——我们可以确信
some_v pure[]
是一个
解析器
,它没有首先递归地检查
某些
纯[]
是什么

(接下来,您将了解
newtype
——当从
data
更改为
newtype
时,您将再次感到困惑,因为这两种实现都可以工作!)

事实“星”:在
()
的实现中:

…我们必须进行足够的计算,以知道这两个解析器实际上都是
解析器
构造函数对某个对象的应用,然后才能转到等号的右侧

事实“管道延迟”:在此实现中:

Parser p1 <|> Parser p2 = ...
p1 <|> p2 = Parser $ ...
让我们看一下您的第一个实现,我们知道“pipe strict”事实。我们想知道
some_v
是否是
解析器
对某事物的应用。由于事实“star”,因此我们必须知道
是否纯(:)
v
some_v纯[]
解析器对某事物的应用程序。要知道最后一个,我们必须知道
是否是某些
纯[]
Parser
对某物的应用。哎呀!我们刚刚演示了要知道
some\u v
是否是
Parser
对某物的应用,我们需要知道
some\u v
是否是
Parser
对某物的应用——一个无限循环

另一方面,在您的第二个实现中,为了检查
some_v
是否是
解析器
,我们仍然必须检查
pure(:)
v
,以及
some_v pure[]
,但由于“管道惰性”这一事实,这就是我们需要检查的全部——我们可以确信
some_v pure[]
是一个
解析器
,它没有首先递归地检查
某些
纯[]
是什么


(接下来,您将了解
newtype
——当从
data
更改为
newtype
时,您将再次感到困惑,因为这两种实现都可以工作!)

此外,如果您使用的是列表而不是Maybe,我希望您的
实现能够无条件地调用这两个解析器,并将它们的结果与
(++)
(Parser p)(Parser q)=Parser$(\s->ps++qs)结合起来
@amalloy:你是对的,但不管怎样,它都会陷入同一个循环。@ShouYa这不仅仅是“这两种不同的方法在概念上是相同的”,而是“你已经粘贴了完全相同的代码两次,并且问为什么它只工作一次”。@amalloy oops我的错。修复:)另外,如果您使用的是列表而不是Maybe,我希望您的
实现能够无条件地调用这两个解析器,并将它们的结果与
(++)
(Parser p)(Parser q)=Parser$(\s->p s++q s)
@amalloy:您是对的,但无论如何它都会陷入同一个循环。@ShouYa不仅仅是“这两种不同的方法在概念上是相同的”,但是“你已经粘贴了两次完全相同的代码,并且问为什么它只工作一次”。@amalloy oops我的错。修复:)
some v = some_v where
    some_v = pure (:) <*> v <*> (some_v <|> pure [])