假設我有這種型別的功能:
once :: (a, b) -> Parser (a, b)
現在,我想重復應用這個決議器(有點像 using >>=)并使用它的最后一個輸出在下一次迭代中提供它。
使用類似的東西
sequence :: (a, b) -> Parser (a, b)
sequence inp = once inp >>= sequence
為第一個決議器指定初始值是行不通的,因為它會一直持續到它不可避免地失敗。相反,我希望它在失敗時停止(有點像many)。
嘗試修復它try會使計算過于復雜(在每次迭代中添加嘗試)。
sequence :: (a, b) -> Parser (a, b)
sequence inp = try (once inp >>= sequence) <|> pure inp
換句話說,我正在尋找一個有點類似于foldlParsers 的函式,它會在下一個 Parser 失敗時停止。
uj5u.com熱心網友回復:
如果您的once決議器在不消耗輸入的情況下立即失敗,則不需要try. 作為一個具體的例子,考慮一個相當愚蠢的once決議器,它使用一對分隔符來決議下一對分隔符:
once :: (Char, Char) -> Parser (Char, Char)
once (c1, c2) = (,) <$ char c1 <*> anyChar <*> anyChar <* char c2
您可以使用以下方法決議嵌套序列:
onces :: (Char, Char) -> Parser (Char, Char)
onces inp = (once inp >>= onces) <|> pure inp
效果很好:
> parseTest (onces ('(',')')) "([])[{}]{xy}xabyDONE"
('a','b')
try僅當您once在決議輸入后可能失敗時才需要。例如,如果不嘗試,以下內容將無法決議:
> parseTest (onces ('(',')')) "([])[not valid]"
parse error at (line 1, column 8):
unexpected "t"
expecting "]"
因為我們[在發現not valid].
(使用try,它回傳正確的('[',']')。)
話雖如此,我不知道您是如何得出使用try使計算“過于復雜”的結論。如果您只是從您所讀到的關于try可能效率低下的內容中猜測,那么您就誤解了。 try如果以某種方式使用它可能會導致問題,而不是導致大量的回溯。這在這里不是問題——最多,你是在回溯一個once,所以不用擔心。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/450275.html
