簡體   English   中英

Haskell 具有變形的一元解析器

[英]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提供FoldableTraversable的實例,但是編譯器可以為您編寫這些實例,並且它們本身不是遞歸的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM