{-# LANGUAGE GADTs #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# OPTIONS_GHC -Wall -Werror #-} module Siphon.Types ( Siphon(..) , Indexed(..) , SiphonError(..) , RowError(..) , CellError(..) ) where import Data.Vector (Vector) import Control.Exception (Exception) import Data.Text (Text) data CellError = CellError { cellErrorColumn :: !Int , cellErrorContent :: !Text } deriving (Show,Read,Eq) newtype Indexed a = Indexed { indexedIndex :: Int } deriving (Eq,Ord,Functor,Show,Read) data SiphonError = SiphonError { siphonErrorRow :: !Int , siphonErrorCause :: !RowError } deriving (Show,Read,Eq) instance Exception SiphonError data RowError = RowErrorParse -- ^ Error occurred parsing the document into cells | RowErrorDecode !(Vector CellError) -- ^ Error decoding the content | RowErrorSize !Int !Int -- ^ Wrong number of cells in the row | RowErrorHeaders !(Vector (Vector CellError)) !(Vector Text) !(Vector Int) -- ^ Three parts: -- (a) Multiple header cells matched the same expected cell, -- (b) Headers that were missing, -- (c) Missing headers that were lambdas. They cannot be -- shown so instead their positions in the 'Siphon' are given. | RowErrorHeaderSize !Int !Int -- ^ Not enough cells in header, expected, actual | RowErrorMalformed !Int -- ^ Error decoding unicode content, column number deriving (Show,Read,Eq) -- | This just actually a specialization of the free applicative. -- Check out @Control.Applicative.Free@ in the @free@ library to -- learn more about this. The meanings of the fields are documented -- slightly more in the source code. Unfortunately, haddock does not -- play nicely with GADTs. data Siphon f c a where SiphonPure :: !a -- function -> Siphon f c a SiphonAp :: !(f c) -- header -> !(c -> Maybe a) -- decoding function -> !(Siphon f c (a -> b)) -- next decoding -> Siphon f c b instance Functor (Siphon f c) where fmap f (SiphonPure a) = SiphonPure (f a) fmap f (SiphonAp h c apNext) = SiphonAp h c ((f .) <$> apNext) instance Applicative (Siphon f c) where pure = SiphonPure SiphonPure f <*> y = fmap f y SiphonAp h c y <*> z = SiphonAp h c (flip <$> y <*> z)