【问题标题】:Parse fixed length text with attoparsec使用 attoparsec 解析固定长度的文本
【发布时间】:2013-02-05 18:14:00
【问题描述】:

我需要用 attoparsec 解析固定长度的字段,但我现在正在努力使用编译器。 我还是个新手,下面的代码是我最接近的解决方案:

> {-# LANGUAGE OverloadedStrings #-}
> import Control.Applicative
> import Data.Text as T
> import Data.Attoparsec.Combinator
> import Data.Attoparsec.Text hiding (take)
> import Data.Char
> import Prelude hiding (take)
>
> type City = Text
> type Ready = Bool
> data CityReady = CR City Ready deriving Show
>
> input = T.unlines ["#London              1",
>                    "#Seoul               0",
>                    "#Tokyo               0",
>                    "#New York            1"]
>
> parseCityReady = many $ CR <$> cityParser <*> readyParser <* endOfLine
>
> cityParser = char '#' *>
>              takeTill isSpace <*
>              skipWhile isHorizontalSpace
>
>
> readyParser = char '1' *> pure True  <|> char '0' *> pure False
>
> main =
>   case parseOnly parseCityReady input of
>      Left err  -> print err
>      Right xs  -> mapM_ print xs
>

这一切都很好,但它只是返回没有空格的城市。

CR "London" True
CR "Seoul" False
CR "Tokyo" False

我尝试使用 applicative 为 City 文本字符串取 20 个字符

> cityParser = char '#' *>
>              take 20

甚至do syntax

> cityParser = do char '#'
>                 city <- take 20
>                 return city

但两种方法都无法编译并出现此错误:

Couldn't match expected type `attoparsec-0.10.4.0:Data.Attoparsec.Internal.Types.Parser
                                Text b0'
            with actual type `Text -> Text'
In the return type of a call of `take'
Probable cause: `take' is applied to too few arguments
In the second argument of `(*>)', namely `take 20'
In the expression: char '#' *> take 20

take 的类型为Int -&gt; Text -&gt; Text 时,是什么导致ghc 请求Text -&gt; Text

如何在 applicative 和 do-syntax 中解决它?

【问题讨论】:

  • 您隐藏了由attoparsec 导出的take 的版本。相反,您使用的是由Text 模块导出的take 函数,这不是您想要的。
  • @sabauma 确实,我应该将 hiding 放在 Data.Text 上。谢谢!
  • @sabauma:如果这是正确答案,您应该发布它

标签: haskell monads applicative attoparsec


【解决方案1】:

所以,您的问题是您隐藏了 take 的多个版本 功能。特别是,您将 take 隐藏在 attoparsec 中,而不是 比 Text 模块中的 take 函数。您需要做的就是 像这样改变你的导入

> import Control.Applicative
> import Data.Attoparsec.Combinator
> import Data.Attoparsec.Text
> import Data.Char
> import Data.Text as T hiding (take)
> import Prelude hiding (take)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2017-11-30
    相关资源
    最近更新 更多