バランスブラケットの問題を解決しようとしています。私は連続IOをしたくないので、むしろgetLineを1回呼び出して、結果の文字列を解析します。したがって、問題を解決する関数は、2つの異なる状態、すなわち入力文字列の消費されていない部分とブラケットスタックを処理します。通常のモナディック関数をモナド変圧器と同等にする
私は、スタック操作するためのいくつかの機能を設定したい:しかし、私はStateTモナドで動作しています、
type Stack = String
pop :: Stack -> (Char,Stack)
pop (x:xs) = (x,xs)
push :: Char -> Stack -> ((),Stack)
push a xs = ((),a:xs)
私は状態のモナドで動作していた場合、すべての良いことだ
balanced :: StateT Stack (State String) Bool
私はスタックに重複したモナドを持たないように言われてきたことは分かっています。私はそれがプッシュとポップの定義を単純化する方法が好きなので、この方法でやっています。
2つの問題:
- どんなに私は何をすべきか、私は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
内側モナドの「状態文字列」の代わりに「リーダー文字列」を使用してみてください。 – dflemstr