[英]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)
對,我們可以運行f
上a
獲得一個新的解析器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.