簡體   English   中英

Haskell中使用GHCi的功能解析器示例

[英]Functional Parser example in Haskell using GHCi

我是學習Haskell的初學者。 這是使用GHCi時遇到的問題。

p :: Parser (Char, Char)
p =  do x <- item
        item
        y <- item
        return (x,y)

item :: Parser Char
item =  P (\inp -> case inp of
                      []     -> []
                      (x:xs) -> [(x,xs)])

item是另一個解析器,其中item :: Parser Char,簡單來說,item是解析字符串

當我加載文件然后執行

parse p "abcdef"

然后顯示一個執行:

*** Exception: You must implement (>>=)

解決這個問題有什么主意嗎?


更新信息:

解析器的定義如下:

newtype Parser a =  P (String -> [(a,String)])

instance Monad Parser where
   return      :: a -> Parser a
   return v    =  P (\inp -> [(v,inp)])

   (>>=)       :: Parser a -> (a -> Parser b) -> Parser b
   p >>= f     = --...

為了使用do表示法,您的Parser必須是Monad的實例:

instance Monad Parser where
  return :: a -> Parser a
  return = -- ...
  (>>=) :: Parser a -> (a -> Parser b) -> Parser b
  p >>= f = -- ...

編譯器需要您填寫return>>=定義。

do記號是語法糖在於desugars使用的>>= (發音為“綁定”)。 例如,您的代碼不符合以下要求:

p :: Parser (Char, Char)
p =  item >>= \x ->
     item >>= \_ ->
     item >>= \y ->
     return (x,y)

或者,使用更明確的括號:

p = item >>= (\x -> item >>= (\_ -> item >>= (\y -> return (x,y))))

>>=描述了如何將Parser a與函數a -> Parser b組合在一起以創建新的Parser b

使用您對Parser的定義,可以正常工作的Monad實例是

instance Monad Parser where
  return a = P $ \s -> [(a,s)]
  p >>= f = P $ concatMap (\(a,s') -> runParser (f a) s') . runParser p
  -- which is equivalent to
  -- p >>= f = P $ \s -> [(b,s'') | (a,s') <- runParser p s, (b,s'') <- runParser (f a) s']

考慮>>=p :: Parser a和函數f :: a -> Parser b

  • 展開時, p接受一個String ,並返回一個(a,String)對的列表

     runParser p :: String -> [(a,String)] 
  • 每個(a,String)對,我們可以運行fa獲得一個新的解析器q

     map go . runParser p :: String -> [(Parser b,String)] where go :: (a, String) -> (Parser b, String) go (a,s') = let q = fa in (q, s') 
  • 如果解開q ,則會得到一個接受String並返回(b, String)對的列表的函數:

     map go . runParser p :: String -> [(String -> [(b,String)],String)] where go :: (a, String) -> (String -> [(b,String)],String) go (a,s') = let q = fa in (runParser q, s') 
  • 我們可以在與a配對的String上運行該函數, a立即獲得`(b,String)對的列表:

     map go . runParser p :: String -> [[(b,String)]] where go :: (a, String) -> [(b,String)] go (a,s') = let q = fa in runParser qs' 
  • 如果我們將結果列表平展,則會得到一個String -> [(b,String)] ,它只是Parser b

     concat . map go . runParser p :: String -> [(b,String)] where go :: (a, String) -> [(b,String)] go (a,s') = let q = fa in runParser qs' 

暫無
暫無

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

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