如何使用attoparsec解析固定长度的非分隔整数



我试图用attoparsec从3个字符解析两个整数。一个示例输入可能看起来像这样:

341

…我想将其解析为:

Constructor 34 1

我有两个解决方案,但有点笨拙:

stdK :: P.Parser Packet
stdK = do
    P.char '1'
    qstr <- P.take 2
    let q = rExt $ P.parseOnly P.decimal qstr
    n <- P.decimal
    return $ Std q n
stdK2 :: P.Parser Packet
stdK2 = do
    P.char '1'
    qn <- P.decimal
    let q = div qn 10
    let n = rem qn 10
    return $ Std q n

一定有更好的方法来实现这么简单的事情。我错过什么了吗?

您的代码片段远不是自包含的(特别是,缺少导入和Packet数据类型的定义),但是您似乎将事情复杂化了。

首先,定义一个一位数整数的解析器。然后,将后者用作两位数整数解析器的构建块。之后,使用应用操作符组合这两个解析器,并为自定义Packet数据类型定义一个解析器。见下文.

注意,你不需要monad的全部功能;在这里,应用解析就足够了。

-- test_attoparsec.hs
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative ((<$>))
import Data.Attoparsec.Text
import Data.Char
data Packet = Std {-# UNPACK #-} !Int
                  {-# UNPACK #-} !Int
  deriving (Show)
stdK :: Parser Packet
stdK = char '1' *> (Std <$> twoDigitInt <*> oneDigitInt)
twoDigitInt :: Parser Int
twoDigitInt = timesTenPlus <$> oneDigitInt <*> oneDigitInt
  where
    timesTenPlus x y = 10 * x + y
oneDigitInt :: Parser Int
oneDigitInt = digitToInt <$> digit

GHCi试验:

λ> :l test_attoparsec.hs
[1 of 1] Compiling Main             ( test_attoparsec.hs, interpreted )
Ok, modules loaded: Main.
λ> :set -XOverloadedStrings 
λ> parseOnly stdK "1341"
Right (Std 34 1)
λ> parseOnly stdK "212"
Left "1: Failed reading: satisfyWith"

相关内容

  • 没有找到相关文章

最新更新