change Indexed to preserve header information for better error messages

This commit is contained in:
Andrew Martin 2016-06-24 08:25:52 -04:00
parent 7178bffaaf
commit af6e520b36
2 changed files with 21 additions and 23 deletions

View File

@ -24,20 +24,20 @@ headless f = DecodingAp Headless f (DecodingPure id)
headed :: content -> (content -> Either String a) -> Decoding Headed content a headed :: content -> (content -> Either String a) -> Decoding Headed content a
headed h f = DecodingAp (Headed h) f (DecodingPure id) headed h f = DecodingAp (Headed h) f (DecodingPure id)
uncheckedRun :: forall content a. uncheckedRun :: forall content a f.
Vector content Vector content
-> Decoding Indexed content a -> Decoding (Indexed f) content a
-> Either (DecodingErrors Indexed content) a -> Either (DecodingErrors f content) a
uncheckedRun v = getEitherWrap . go uncheckedRun v = getEitherWrap . go
where where
go :: forall b. go :: forall b.
Decoding Indexed content b Decoding (Indexed f) content b
-> EitherWrap (DecodingErrors Indexed content) b -> EitherWrap (DecodingErrors f content) b
go (DecodingPure b) = EitherWrap (Right b) go (DecodingPure b) = EitherWrap (Right b)
go (DecodingAp (Indexed ix) decode apNext) = go (DecodingAp ixed@(Indexed ix h) decode apNext) =
let rnext = go apNext let rnext = go apNext
content = Vector.unsafeIndex v ix content = Vector.unsafeIndex v ix
rcurrent = mapLeft (DecodingErrors . Vector.singleton . DecodingError content (Indexed ix)) (decode content) rcurrent = mapLeft (DecodingErrors . Vector.singleton . DecodingError content ixed) (decode content)
in rnext <*> (EitherWrap rcurrent) in rnext <*> (EitherWrap rcurrent)
-- | Maps over a 'Decoding' that expects headers, converting these -- | Maps over a 'Decoding' that expects headers, converting these
@ -46,14 +46,14 @@ uncheckedRun v = getEitherWrap . go
headedToIndexed :: forall content a. Eq content headedToIndexed :: forall content a. Eq content
=> Vector content -- ^ Headers in the source document => Vector content -- ^ Headers in the source document
-> Decoding Headed content a -- ^ Decoding that contains expected headers -> Decoding Headed content a -- ^ Decoding that contains expected headers
-> Either (HeadingErrors content) (Decoding Indexed content a) -> Either (HeadingErrors content) (Decoding (Indexed Headed) content a)
headedToIndexed v = go headedToIndexed v = getEitherWrap . go
where where
go :: forall b. Eq content go :: forall b. Eq content
=> Decoding Headed content b => Decoding Headed content b
-> Either (HeadingErrors content) (Decoding Indexed content b) -> EitherWrap (HeadingErrors content) (Decoding (Indexed Headed) content b)
go (DecodingPure b) = Right (DecodingPure b) go (DecodingPure b) = EitherWrap (Right (DecodingPure b))
go (DecodingAp (Headed h) decode apNext) = go (DecodingAp hd@(Headed h) decode apNext) =
let rnext = go apNext let rnext = go apNext
ixs = Vector.elemIndices h v ixs = Vector.elemIndices h v
ixsLen = Vector.length ixs ixsLen = Vector.length ixs
@ -61,13 +61,9 @@ headedToIndexed v = go
| ixsLen == 1 = Right (Vector.unsafeIndex ixs 0) | ixsLen == 1 = Right (Vector.unsafeIndex ixs 0)
| ixsLen == 0 = Left (HeadingErrors (Vector.singleton h) Vector.empty) | ixsLen == 0 = Left (HeadingErrors (Vector.singleton h) Vector.empty)
| otherwise = Left (HeadingErrors Vector.empty (Vector.singleton (h,ixsLen))) | otherwise = Left (HeadingErrors Vector.empty (Vector.singleton (h,ixsLen)))
in case rcurrent of in (\ix ap -> DecodingAp (Indexed ix hd) decode ap)
Right ix -> case rnext of <$> EitherWrap rcurrent
Right apIx -> Right (DecodingAp (Indexed ix) decode apIx) <*> rnext
Left errNext -> Left errNext
Left err -> case rnext of
Right _ -> Left err
Left errNext -> Left (mappend err errNext)
eitherMonoidAp :: Monoid a => Either a (b -> c) -> Either a b -> Either a c eitherMonoidAp :: Monoid a => Either a (b -> c) -> Either a b -> Either a c
eitherMonoidAp = go where eitherMonoidAp = go where

View File

@ -29,8 +29,10 @@ data Headless a = Headless
deriving (Eq,Ord,Functor,Show,Read) deriving (Eq,Ord,Functor,Show,Read)
-- | Isomorphic to @'Const' 'Int'@ -- | Isomorphic to @'Const' 'Int'@
newtype Indexed a = Indexed { getIndexed :: Int } data Indexed f a = Indexed
deriving (Eq,Ord,Functor,Show,Read) { indexedIndex :: Int
, indexedHeading :: f a
} deriving (Eq,Ord,Functor,Show,Read)
data HeadingErrors content = HeadingErrors data HeadingErrors content = HeadingErrors
{ headingErrorsMissing :: Vector content -- ^ headers that were missing { headingErrorsMissing :: Vector content -- ^ headers that were missing
@ -47,7 +49,7 @@ instance Monoid (HeadingErrors content) where
data DecodingError f content = DecodingError data DecodingError f content = DecodingError
{ decodingErrorContent :: content { decodingErrorContent :: content
, decodingErrorHeader :: f content , decodingErrorHeader :: Indexed f content
, decodingErrorMessage :: String , decodingErrorMessage :: String
} -- deriving (Show,Read) } -- deriving (Show,Read)