Разбирать текст фиксированной длины с attoparsec

Мне нужно разобрать поля фиксированной длины с помощью 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

Я попытался использовать аппликатив, чтобы взять 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

Что заставляет ghc запрашивать Text -> Text, когда take имеет тип Int -> Text -> Text?

Как мне решить это как в аппликативном, так и в do-синтаксисе?


person georgina    schedule 05.02.2013    source источник
comment
Вы скрываете версию take, экспортированную attoparsec. Вместо этого вы используете функцию take, экспортированную модулем Text, которая вам не нужна.   -  person sabauma    schedule 05.02.2013
comment
@sabauma действительно, вместо этого я должен был поместить hiding в Data.Text. Спасибо!   -  person georgina    schedule 05.02.2013
comment
@sabauma: если это правильный ответ, ты должен опубликовать его   -  person sclv    schedule 05.02.2013


Ответы (1)


Итак, ваша проблема в том, что вы скрываете несколько версий функции take. В частности, вы скрываете функцию take из модуля attoparsec, а не функцию take из модуля Text. Все, что вам нужно сделать, это изменить свой импорт следующим образом

> 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)
person sabauma    schedule 05.02.2013