I need to parse fixed length fields with attoparsec but im now struggling with the compiler.
Im still a newbie, the code below is the closest solution I have:
> {-# 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
>
This is all great but it is only returning Cities without spaces.
CR "London" True
CR "Seoul" False
CR "Tokyo" False
I have tried using applicative to take 20 characters for the City text string
> cityParser = char '#' *>
> take 20
and even do syntax
> cityParser = do char '#'
> city <- take 20
> return city
but both approaches fail to compile with this error:
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
What is causing the ghc to ask for Text -> Text when the take has a type of Int -> Text -> Text?
How do I solve it in both applicative and do-syntax?
So, your problem is that you are hiding several versions of the
takefunction. In particular, you are hiding the
takefromattoparsecratherthan the
takefunction from theTextmodule. All you should need to do ischange your imports like so