使用 attoparsec 库,我在这里编写了这个函数:
satisfyMaybe :: (Char -> Maybe a) -> Parser a
satisfyMaybe f =
(fromJust . f) <$> satisfy (isJust . f)
这基本上将
f
应用于下一个字符,如果它是 Just x
,则返回 x
,否则解析失败。
问题是,如果不使用像
fromJust
这样可能失败的函数,我无法弄清楚如何编写这个。我相信我上面的代码无论如何都是正确的并且永远不会失败,但是如果我需要一个不安全的函数只是为了有条件地将函数应用于输入文本中的字符,我觉得我使用了错误的库。
有没有办法使用库来编写这个函数而无需
fromJust
或类似的不完整函数?
satisfyWith :: (Word8 -> a) -> (a -> Bool) -> Parser a
[Hackage] 所做的 [src]:
satisfyWith :: (Word8 -> a) -> (a -> Bool) -> Parser a satisfyWith f p = do h <- peekWord8' let c = f h if p c then advance 1 >> return c else fail "satisfyWith" {-# INLINE satisfyWith #-}
因此,它首先查看下一个
word8'
,如果满足条件p c
,则前进并返回c
,否则失败。
因此我们可以将其用作:
import Data.ByteString.Internal(w2c)
satisfyMaybe :: (Char -> Maybe a) -> Parser a
satisfyMaybe f p = do
h <- peekWord8'
case f (c2w h) of
Just r -> advance 1 >> pure r
_ -> fail "satisfyMaybe"