gpt4 book ai didi

haskell - 如何使用应用程序链接任意长度的原子解析器系列?

转载 作者:行者123 更新时间:2023-12-04 23:56:14 28 4
gpt4 key购买 nike

假设我有这种解析器类型:

newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }

这个原子解析器单元:
satisfy :: ( Char -> Bool ) -> Parser Char
satisfy g = Parser $ \stream -> case stream of
(x:xs) | g x -> Just ( x, xs )
otherwise -> Nothing

解析器实现了这三个接口(interface):
instance Functor Parser where
fmap g ( Parser p ) = Parser $ \xs0 -> p xs0 >>= \(x,xs) -> return ( g x, xs )


instance Applicative Parser where
pure a = Parser $ \xs0 -> Just ( a, xs0 )
(Parser p1) <*> (Parser p2) = Parser $ \xs0 -> do
(x1, xs1) <- p1 xs0
(x2, xs2) <- p2 xs1
return ( x1 x2, xs2 )

instance Alternative Parser where
empty = Parser $ const Nothing
(Parser p1) <|> (Parser p2) = Parser $ \ss -> let ss1 = p1 ss in case ss1 of
Nothing -> p2 ss
_ -> ss1

现在据我了解,我现在可以通过链接 satisfy 弹出更高级别的抽象并构建更复杂的解析器。使用应用程序接口(interface)。例如:
-- | A parser that parses the first two chars in the stream if they are upper case
uParser = satisfy isUpper
parser1 = ( (:) <$> uParser ) <*> ( (\x -> [x]) <$> uParser )
runParser parser1 "HEllo" = Just ("HE","llo")
runParser parser1 "Hello" = Nothing

太好了,现在如果我想构造一个计算,以便解析器解析流中的所有大写字母,直到遇到小写字母,该怎么办?用例:
runParser idealParser "hello"             = Nothing
runParser idealParser "HEllo" = Just ("HE","llo")
runParser idealParser "HELLOIAMnotincaps" = Just ("HELLOIAM", "notincaps")

我如何表达这种不确定长度的概念?

最佳答案

既然你有 Alternative例如,您可以简单地使用 Control.Applicative.some 匹配一个或多个事件的列表。

> runParser (some uParser) "hello"
Nothing
> runParser (some uParser) "HEllo"
Just ("HE","llo")
> runParser (some uParser) "HELLOIAMnotincaps"
Just ("HELLOIAM","notincaps")

要手动实现它,您可以使用两个相互递归的解析器,例如
zeroOrMore = oneOrMore <|> pure []
oneOrMore = (:) <$> uParser <*> zeroOrMore

关于haskell - 如何使用应用程序链接任意长度的原子解析器系列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16006279/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com