作为一个辅助项目,我正在努力实现自己的Regex parser/compiler。
我认为实际的匹配部分是学习一些回溯单元如何工作的好时机;比如列表monad例如。
我最终构建了我的'匹配'算法,如下所示:
data Expr
= Group Int Expr
| Terms [Expr]
| OneOf [Expr]
| Repetition Expr Int (Maybe Int)
| Empty
| BackRef Int
| Wildcard
| Atom Char
| Start
| End
deriving (Show)
data RState = RState
{ groups :: Groups
, leftover :: String
} deriving Show
match :: Expr -> ListT (State RState) String
其中ListT来自Gabriel的List.Transformer lib
状态monad部分跟踪已捕获的组(以便在我对后引用进行匹配时可以使用它们)并留下剩余的字符串以供使用。 Expr
是一个数据结构,表示正则表达式是一种AST。
反正;这很有效;我试图进行匹配,如果匹配成功,我返回匹配部分作为结果并相应地更改状态中的剩余和组,这最终会在非确定性中工作,因为它将继续尝试继续使用所有可能的先前匹配试图处理正则表达式的下一部分。问题是它只是回溯了之前的结果,而不是之前的状态!因此,我的alternative
匹配代码用于匹配正则表达式中的可选项链(例如a | b * | c;其中每个部分是'term')如下所示:
match (OneOf terms) = do
st <- get
-- Backtrack the state and try again on each alternative
let try t = put st >> match t
asum (try <$> terms)
基本上我尝试匹配每个术语,但即使比赛失败,它仍然会改变状态!所以我需要在两次失败之间手动倒回状态。这是由于<|>
的ListT实现:
ListT m <|> l = ListT (do
s <- m
case s of
Nil -> next l
Cons x l' -> return (Cons x (l' <|> l)) )
我们看到它运行底层monad并继续在相同的上下文中。
我想要类似的东西:
ListT m <|> l = ListT (do
st <- get
s <- m
case s of
Nil -> put st >> next l
Cons x l' -> return (Cons x (l' <|> l)) )
......但是对于所有monad效果一般;我甚至不确定这是否可行。
我查看Logic Monad作为一种可能的解决方案,但即使在阅读完论文之后,我也无法确定它是否可以做我想要的,也许可以使用ifte
?
是否有一个回溯monad,不仅回溯了monad的结果,还有monadic计算?我想这对IO这样的事情来说是不可能的,但理论上对纯monad来说应该是可能的吗?我想这意味着一般来说这是不可能的,但是我可以实现一个类型类来为我的案例获得这个功能吗?
谢谢!我知道我在这里大声说话,谢谢你帮助我思考这个问题!
答案 0 :(得分:2)
正如@danidiaz建议的那样,解决方案是颠倒堆栈。
我发现外部monad变形金刚受到内在变形金刚的支配是有帮助的。因此SomeMonadT (State s)
无论SomeMonadT
是什么,都会在其有状态中成为“单线程”。
一个有启发性的例子是将StateT
monad变换器展开到其他monad上。假设我们有:
foo :: StateT S M A
bar :: StateT S M B
do a <- foo
b <- bar
return (a,b)
这只是一种奇特的写作方式:
foo :: S -> M (A, S)
bar :: S -> M (B, S)
\s1 -> do
(a,s2) <- foo s1
(b,s3) <- bar s2
return ((a,b),s3)
这是激发State
monad的熟悉模式,除了模式发生在另一个monadic上下文中。这种背景是王道,变压器无能为力。
这意味着ListT (State s)
是一个跟踪一个状态s
的计算,然后顶部有一些“糖”,由ListT
定义。您可以将其视为有状态机器中的非确定性实现(仅具有跟踪单个状态的能力)。
而StateT s []
是一个基本上不确定的计算,然后有一些模仿状态的“糖”。底层机器是一个不确定性的回溯机器,然后变换器使用编码模式来模拟该机器上的状态。
这是Dan Piponi的diagram,它有助于给出一些直觉:
这是一个有点虚伪和直觉的领域,所以我希望这有用。