如何使用`attoparsec`有条件地转换字符?

问题描述 投票:0回答:1

使用 attoparsec 库,我在这里编写了这个函数:

satisfyMaybe :: (Char -> Maybe a) -> Parser a
satisfyMaybe f =
  (fromJust . f) <$> satisfy (isJust . f)

这基本上将

f
应用于下一个字符,如果它是
Just x
,则返回
x
,否则解析失败。

问题是,如果不使用像

fromJust
这样可能失败的函数,我无法弄清楚如何编写这个。我相信我上面的代码无论如何都是正确的并且永远不会失败,但是如果我需要一个不安全的函数只是为了有条件地将函数应用于输入文本中的字符,我觉得我使用了错误的库。

有没有办法使用库来编写这个函数而无需

fromJust
或类似的不完整函数?

parsing haskell attoparsec
1个回答
0
投票

本质上我们可以复制

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"
© www.soinside.com 2019 - 2024. All rights reserved.