Parsing 如何限制monad transformer解析器组合器中的回溯

Parsing 如何限制monad transformer解析器组合器中的回溯,parsing,haskell,monad-transformers,parser-combinators,monadplus,Parsing,Haskell,Monad Transformers,Parser Combinators,Monadplus,tl;dr,如果解析器是monad transformer堆栈,如何实现其回溯可以受到限制的解析器 我还没有找到任何关于这种方法的论文、博客或示例实现;限制回溯的典型方法似乎是使用附加构造函数的数据类型,或者默认情况下禁用回溯的Parsec方法 我当前的实现——使用commitcombinator,见下文——是错误的;我不确定类型,它是否属于类型类,并且我的实例不像它感觉的那样通用 有谁能清楚地描述一下如何做到这一点,或者给我指一下参考资料吗 我在下面添加了我当前的代码;对不起,帖子太长了 堆

tl;dr,如果解析器是monad transformer堆栈,如何实现其回溯可以受到限制的解析器

我还没有找到任何关于这种方法的论文、博客或示例实现;限制回溯的典型方法似乎是使用附加构造函数的数据类型,或者默认情况下禁用回溯的Parsec方法

我当前的实现——使用
commit
combinator,见下文——是错误的;我不确定类型,它是否属于类型类,并且我的实例不像它感觉的那样通用

有谁能清楚地描述一下如何做到这一点,或者给我指一下参考资料吗

我在下面添加了我当前的代码;对不起,帖子太长了


堆栈:

StateT
MaybeT/ListT
Either e

的意图是回溯在中间层中进行操作——A<代码> No.< /代码>或空列表不一定会产生错误,它只是意味着应该尝试一个不同的分支——而底层则是错误(具有一些上下文信息),从而立即中止解析。

{-# LANGUAGE NoMonomorphismRestriction, FunctionalDependencies, 
             FlexibleInstances, UndecidableInstances #-}

import Control.Monad.Trans.State   (StateT(..))
import Control.Monad.State.Class   (MonadState(..))
import Control.Monad.Trans.Maybe   (MaybeT(..))
import Control.Monad.Trans.List    (ListT(..))
import Control.Monad               (MonadPlus(..), guard)    

type Parser e t mm a = StateT [t] (mm (Either e)) a

newtype DParser e t a = 
    DParser {getDParser :: Parser e t MaybeT a}

instance Monad (DParser e t) where
  return = DParser . return
  (DParser d) >>= f = DParser (d >>= (getDParser . f))

instance MonadPlus (DParser e t) where
  mzero = DParser (StateT (const (MaybeT (Right Nothing))))
  mplus = undefined   -- will worry about later

instance MonadState [t] (DParser e t) where
  get = DParser get
  put = DParser . put
几个解析类:

class (Monad m) => MonadParser t m n | m -> t, m -> n where
  item  :: m t
  parse :: m a -> [t] -> n (a, [t])

class (Monad m, MonadParser t m n) => CommitParser t m n where
  commit :: m a -> m a
他们的例子:

instance MonadParser t (DParser e t) (MaybeT (Either e)) where
  item = 
      get >>= \xs -> case xs of
                          (y:ys) -> put ys >> return y;
                          []     -> mzero;
  parse = runStateT . getDParser

instance CommitParser t (DParser [t] t) (MaybeT (Either [t])) where
  commit p =
      DParser (
        StateT (\ts -> MaybeT $ case runMaybeT (parse p ts) of
                            Left e          ->  Left e;
                            Right Nothing   ->  Left ts;
                            Right (Just x)  ->  Right (Just x);))
还有几个组合器:

satisfy f = 
    item >>= \x ->
    guard (f x) >>
    return x

literal x = satisfy (== x)
然后这些解析器:

ab = literal 'a' >> literal 'b'

ab' = literal 'a' >> commit (literal 'b')
给出以下结果:

> myParse ab "abcd"
Right (Just ('b',"cd"))  -- succeeds

> myParse ab' "abcd"
Right (Just ('b',"cd"))  -- 'commit' doesn't affect success

> myParse ab "acd"
Right Nothing       -- <== failure but not an error

> myParse ab' "acd"
Left "cd"           -- <== error b/c of 'commit'
>myParse ab“abcd”
对(只是('b','cd')——成功
>myParse ab的“abcd”
对(只是('b','cd')-'commit'不影响成功
>myParse ab“acd”
什么都没有——myParse ab的“acd”

左“cd”-答案似乎在中(不幸的是,它不是标准库的一部分):

满足幺半群和左捕捉:

morelse mzero b = b 
morelse a mzero = a 
morelse (morelse a b) c = morelse a (morelse b c) 
morelse (return a) b = return a

我可能遗漏了一些东西,但是你给出的结果是你想要的还是你目前得到的。(如果是后者,您希望得到什么结果?@dbaupp二者——代码现在“工作”,但仅适用于特定的monad堆栈。我的目标是找到“正确”的方法,或者至少是更好/更干净/通用的方法。
morelse mzero b = b 
morelse a mzero = a 
morelse (morelse a b) c = morelse a (morelse b c) 
morelse (return a) b = return a