module Data.Sv.Decode.Type (
Decode (..)
, Decode'
, buildDecode
, DecodeState (..)
, runDecodeState
, Ind (..)
, DecodeError (..)
, DecodeErrors (..)
, DecodeValidation
, Validation (..)
) where
import Control.DeepSeq (NFData)
import Control.Monad.Reader (ReaderT (ReaderT, runReaderT), MonadReader, withReaderT)
import Control.Monad.State (State, runState, state, MonadState)
import Data.Functor.Alt (Alt ((<!>)))
import Data.Functor.Apply (Apply)
import Data.Functor.Bind (Bind ((>>-)))
import Data.Functor.Compose (Compose (Compose))
import Data.List.NonEmpty
import Data.Semigroup
import Data.Profunctor (Profunctor (lmap, rmap))
import Data.Validation (Validation (Success, Failure))
import Data.Vector (Vector)
import GHC.Generics (Generic)
import Data.Sv.Syntax.Field (SpacedField)
newtype Decode e s a =
Decode { unwrapDecode :: Compose (DecodeState s) (DecodeValidation e) a }
deriving (Functor, Apply, Applicative)
type Decode' s = Decode s s
instance Alt (Decode e s) where
Decode (Compose as) <!> Decode (Compose bs) =
buildDecode $ \v i ->
case runDecodeState as v i of
(a, j) -> case runDecodeState bs v i of
(b, k) ->
let a' = fmap (,j) a
b' = fmap (,k) b
in case a' <!> b' of
Failure e -> (Failure e, k)
Success (z, m) -> (Success z, m)
instance Profunctor (Decode e) where
lmap f (Decode (Compose dec)) = Decode (Compose (lmap f dec))
rmap = fmap
newtype DecodeState s a =
DecodeState { getDecodeState :: ReaderT (Vector (SpacedField s)) (State Ind) a }
deriving (Functor, Apply, Applicative, Monad, MonadReader (Vector (SpacedField s)), MonadState Ind)
instance Bind (DecodeState s) where
(>>-) = (>>=)
instance Profunctor DecodeState where
lmap f (DecodeState s) = DecodeState (withReaderT (fmap (fmap (fmap f))) s)
rmap = fmap
buildDecode :: (Vector (SpacedField s) -> Ind -> (DecodeValidation e a, Ind)) -> Decode e s a
buildDecode f = Decode . Compose . DecodeState . ReaderT $ \v -> state $ \i -> f v i
runDecodeState :: DecodeState s a -> Vector (SpacedField s) -> Ind -> (a, Ind)
runDecodeState = fmap runState . runReaderT . getDecodeState
newtype Ind = Ind Int
data DecodeError e =
UnexpectedEndOfRow
| ExpectedEndOfRow (Vector (SpacedField e))
| UnknownCategoricalValue e [[e]]
| BadParse e
| BadDecode e
deriving (Eq, Ord, Show, Generic)
instance Functor DecodeError where
fmap f d = case d of
UnexpectedEndOfRow -> UnexpectedEndOfRow
ExpectedEndOfRow v -> ExpectedEndOfRow (fmap (fmap (fmap f)) v)
UnknownCategoricalValue e ess -> UnknownCategoricalValue (f e) (fmap (fmap f) ess)
BadParse e -> BadParse (f e)
BadDecode e -> BadDecode (f e)
instance NFData e => NFData (DecodeError e)
newtype DecodeErrors e =
DecodeErrors (NonEmpty (DecodeError e))
deriving (Eq, Ord, Show, Semigroup, Generic)
instance Functor DecodeErrors where
fmap f (DecodeErrors nel) = DecodeErrors (fmap (fmap f) nel)
instance NFData e => NFData (DecodeErrors e)
type DecodeValidation e = Validation (DecodeErrors e)