我正在尝试解决平衡括号问题。我不想做连续的 IO,而宁愿只调用一次 getLine 并解析结果字符串。因此,解决问题的函数将处理两种不同的状态:输入字符串的未使用部分和括号堆栈。
我想设置一些函数来操作堆栈:
type Stack = String
pop :: Stack -> (Char,Stack)
pop (x:xs) = (x,xs)
push :: Char -> Stack -> ((),Stack)
push a xs = ((),a:xs)
如果我在 state monad 中操作,那一切都很好,但是我在 StateT monad 中操作
balanced :: StateT Stack (State String) Bool
我知道我被告知不要在堆栈中有重复的单子。我这样做是因为我喜欢它简化 push 和 pop 定义的方式。
两个问题:
- 无论我做什么,我都找不到将推送和弹出应用到 StateT 中包含的堆栈的方法。
- 我不知道如何从主函数调用它
这是其余的代码
next :: String -> (Maybe Char,String)
next "" = (Nothing,[])
next (x:xs) = (Just x,xs)
balanced = do
c <- lift (state next)
case c of
Nothing -> return True
Just c -> if elem c open
then (push c) >> balanced
else if elem c close
then pop >>= \x ->
if eq x c
then balanced
else return False
else balanced
where open = "<{(["
close = "])}>"
eq '(' ')' = True
eq '{' '}' = True
eq '<' '>' = True
eq '[' ']' = True
eq _ _ = False