[英]Haskell monadic parser with anamorphisms
我的問題是如何將遞歸的 F 代數風格的遞歸類型定義與單子/應用風格的解析器結合起來,以適應現實的編程語言。
我剛剛開始使用下面的Expr
定義:
data ExprF a = Plus a a |
Val Integer deriving (Functor,Show)
data Rec f = In (f (Rec f))
type Expr = Rec ExprF
我正在嘗試將它與使用變形的解析器結合起來:
ana :: Functor f => (a -> f a) -> a -> Rec f
ana psi x = In $ fmap (ana psi) (psi x)
parser = ana psi
where psi :: String -> ExprF String
psi = ???
據我所知,在我的示例中, psi
應該僅解析 integer,或者它應該確定字符串是<expr> + <expr>
然后(通過遞歸調用fmap (ana psi)
),它應該解析左側和右側表達式。
但是,(monadic/applicative)解析器不是這樣工作的:
+
,我看到的一種解決方案是將Plus aa
的類型定義更改為Plus Integer a
,以便它反映解析過程,但這似乎不是最好的途徑。
歡迎任何建議(或閱讀指導)!
如果你需要一個單子解析器,你需要一個單子在你的展開:
anaM :: (Traversable f, Monad m) => (a -> m (f a)) -> a -> m (Rec f)
anaM psiM x = In <$> (psiM x >>= traverse (anaM psiM))
然后你可以編寫一些只解析ExprF
的一個級別的東西,如下所示:
parseNum :: Parser Integer
parseNum = -- ...
char :: Char -> Parser Char
char c = -- ...
parseExprF :: Maybe Integer -> Parser (ExprF (Maybe Integer))
parseExprF (Just n) = pure (Val n)
parseExprF Nothing = do
n <- parseNum
empty
<|> (Plus (Just n) Nothing <$ char '+')
<|> (pure (Val n))
鑒於此,您現在擁有遞歸Expr
解析器:
parseExpr :: Parser Expr
parseExpr = anaM parseExprF Nothing
當然,您需要為ExprF
提供Foldable
和Traversable
的實例,但是編譯器可以為您編寫這些實例,並且它們本身不是遞歸的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.