{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE RecordWildCards #-} -- | -- Module : Data.Pagination -- Copyright : © 2016–present Mark Karpov -- License : BSD 3 clause -- -- Maintainer : Mark Karpov <markkarpov92@gmail.com> -- Stability : experimental -- Portability : portable -- -- Framework-agnostic pagination boilerplate. module Data.Pagination ( -- * Pagination settings Pagination, mkPagination, pageSize, pageIndex, -- * Paginated data Paginated, paginate, paginatedItems, paginatedPagination, paginatedPagesTotal, paginatedItemsTotal, hasOtherPages, pageRange, hasPrevPage, hasNextPage, backwardEllip, forwardEllip, -- * Exceptions PaginationException (..), ) where import Control.DeepSeq import Control.Monad.Catch import Data.Data (Data) import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NE import Data.Typeable (Typeable) import GHC.Generics import Numeric.Natural ---------------------------------------------------------------------------- -- Pagination settings -- | Settings that are required to organize data in paginated form. data Pagination = Pagination Natural Natural deriving (Pagination -> Pagination -> Bool (Pagination -> Pagination -> Bool) -> (Pagination -> Pagination -> Bool) -> Eq Pagination forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: Pagination -> Pagination -> Bool $c/= :: Pagination -> Pagination -> Bool == :: Pagination -> Pagination -> Bool $c== :: Pagination -> Pagination -> Bool Eq, Int -> Pagination -> ShowS [Pagination] -> ShowS Pagination -> String (Int -> Pagination -> ShowS) -> (Pagination -> String) -> ([Pagination] -> ShowS) -> Show Pagination forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [Pagination] -> ShowS $cshowList :: [Pagination] -> ShowS show :: Pagination -> String $cshow :: Pagination -> String showsPrec :: Int -> Pagination -> ShowS $cshowsPrec :: Int -> Pagination -> ShowS Show, Typeable Pagination DataType Constr Typeable Pagination -> (forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Pagination -> c Pagination) -> (forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Pagination) -> (Pagination -> Constr) -> (Pagination -> DataType) -> (forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Pagination)) -> (forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Pagination)) -> ((forall b. Data b => b -> b) -> Pagination -> Pagination) -> (forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Pagination -> r) -> (forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Pagination -> r) -> (forall u. (forall d. Data d => d -> u) -> Pagination -> [u]) -> (forall u. Int -> (forall d. Data d => d -> u) -> Pagination -> u) -> (forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> Pagination -> m Pagination) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> Pagination -> m Pagination) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> Pagination -> m Pagination) -> Data Pagination Pagination -> DataType Pagination -> Constr (forall b. Data b => b -> b) -> Pagination -> Pagination (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Pagination -> c Pagination (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Pagination forall a. Typeable a -> (forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> a -> c a) -> (forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c a) -> (a -> Constr) -> (a -> DataType) -> (forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c a)) -> (forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a)) -> ((forall b. Data b => b -> b) -> a -> a) -> (forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r) -> (forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r) -> (forall u. (forall d. Data d => d -> u) -> a -> [u]) -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u) -> (forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> a -> m a) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a) -> Data a forall u. Int -> (forall d. Data d => d -> u) -> Pagination -> u forall u. (forall d. Data d => d -> u) -> Pagination -> [u] forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Pagination -> r forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Pagination -> r forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> Pagination -> m Pagination forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> Pagination -> m Pagination forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Pagination forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Pagination -> c Pagination forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Pagination) forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Pagination) $cPagination :: Constr $tPagination :: DataType gmapMo :: (forall d. Data d => d -> m d) -> Pagination -> m Pagination $cgmapMo :: forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> Pagination -> m Pagination gmapMp :: (forall d. Data d => d -> m d) -> Pagination -> m Pagination $cgmapMp :: forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> Pagination -> m Pagination gmapM :: (forall d. Data d => d -> m d) -> Pagination -> m Pagination $cgmapM :: forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> Pagination -> m Pagination gmapQi :: Int -> (forall d. Data d => d -> u) -> Pagination -> u $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Pagination -> u gmapQ :: (forall d. Data d => d -> u) -> Pagination -> [u] $cgmapQ :: forall u. (forall d. Data d => d -> u) -> Pagination -> [u] gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Pagination -> r $cgmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Pagination -> r gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Pagination -> r $cgmapQl :: forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Pagination -> r gmapT :: (forall b. Data b => b -> b) -> Pagination -> Pagination $cgmapT :: (forall b. Data b => b -> b) -> Pagination -> Pagination dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Pagination) $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Pagination) dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Pagination) $cdataCast1 :: forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Pagination) dataTypeOf :: Pagination -> DataType $cdataTypeOf :: Pagination -> DataType toConstr :: Pagination -> Constr $ctoConstr :: Pagination -> Constr gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Pagination $cgunfold :: forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Pagination gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Pagination -> c Pagination $cgfoldl :: forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Pagination -> c Pagination $cp1Data :: Typeable Pagination Data, Typeable, (forall x. Pagination -> Rep Pagination x) -> (forall x. Rep Pagination x -> Pagination) -> Generic Pagination forall x. Rep Pagination x -> Pagination forall x. Pagination -> Rep Pagination x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep Pagination x -> Pagination $cfrom :: forall x. Pagination -> Rep Pagination x Generic) instance NFData Pagination -- | Create a 'Pagination' value. May throw 'PaginationException'. mkPagination :: MonadThrow m => -- | Page size Natural -> -- | Page index Natural -> -- | The pagination settings m Pagination mkPagination :: Natural -> Natural -> m Pagination mkPagination Natural size Natural index | Natural size Natural -> Natural -> Bool forall a. Eq a => a -> a -> Bool == Natural 0 = PaginationException -> m Pagination forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a throwM PaginationException ZeroPageSize | Natural index Natural -> Natural -> Bool forall a. Eq a => a -> a -> Bool == Natural 0 = PaginationException -> m Pagination forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a throwM PaginationException ZeroPageIndex | Bool otherwise = Pagination -> m Pagination forall (m :: * -> *) a. Monad m => a -> m a return (Natural -> Natural -> Pagination Pagination Natural size Natural index) -- | Get page size (maximum number of items on a page) from a 'Pagination'. pageSize :: Pagination -> Natural pageSize :: Pagination -> Natural pageSize (Pagination Natural size Natural _) = Natural size -- | Get page index from a 'Pagination'. pageIndex :: Pagination -> Natural pageIndex :: Pagination -> Natural pageIndex (Pagination Natural _ Natural index) = Natural index ---------------------------------------------------------------------------- -- Paginated data -- | Data in the paginated form. data Paginated a = Paginated { Paginated a -> [a] pgItems :: [a], Paginated a -> Pagination pgPagination :: Pagination, Paginated a -> Natural pgPagesTotal :: Natural, Paginated a -> Natural pgItemsTotal :: Natural } deriving (Paginated a -> Paginated a -> Bool (Paginated a -> Paginated a -> Bool) -> (Paginated a -> Paginated a -> Bool) -> Eq (Paginated a) forall a. Eq a => Paginated a -> Paginated a -> Bool forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: Paginated a -> Paginated a -> Bool $c/= :: forall a. Eq a => Paginated a -> Paginated a -> Bool == :: Paginated a -> Paginated a -> Bool $c== :: forall a. Eq a => Paginated a -> Paginated a -> Bool Eq, Int -> Paginated a -> ShowS [Paginated a] -> ShowS Paginated a -> String (Int -> Paginated a -> ShowS) -> (Paginated a -> String) -> ([Paginated a] -> ShowS) -> Show (Paginated a) forall a. Show a => Int -> Paginated a -> ShowS forall a. Show a => [Paginated a] -> ShowS forall a. Show a => Paginated a -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [Paginated a] -> ShowS $cshowList :: forall a. Show a => [Paginated a] -> ShowS show :: Paginated a -> String $cshow :: forall a. Show a => Paginated a -> String showsPrec :: Int -> Paginated a -> ShowS $cshowsPrec :: forall a. Show a => Int -> Paginated a -> ShowS Show, Typeable (Paginated a) DataType Constr Typeable (Paginated a) -> (forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Paginated a -> c (Paginated a)) -> (forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Paginated a)) -> (Paginated a -> Constr) -> (Paginated a -> DataType) -> (forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Paginated a))) -> (forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Paginated a))) -> ((forall b. Data b => b -> b) -> Paginated a -> Paginated a) -> (forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r) -> (forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r) -> (forall u. (forall d. Data d => d -> u) -> Paginated a -> [u]) -> (forall u. Int -> (forall d. Data d => d -> u) -> Paginated a -> u) -> (forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a)) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a)) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a)) -> Data (Paginated a) Paginated a -> DataType Paginated a -> Constr (forall d. Data d => c (t d)) -> Maybe (c (Paginated a)) (forall b. Data b => b -> b) -> Paginated a -> Paginated a (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Paginated a -> c (Paginated a) (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Paginated a) forall a. Data a => Typeable (Paginated a) forall a. Data a => Paginated a -> DataType forall a. Data a => Paginated a -> Constr forall a. Data a => (forall b. Data b => b -> b) -> Paginated a -> Paginated a forall a u. Data a => Int -> (forall d. Data d => d -> u) -> Paginated a -> u forall a u. Data a => (forall d. Data d => d -> u) -> Paginated a -> [u] forall a r r'. Data a => (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r forall a r r'. Data a => (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r forall a (m :: * -> *). (Data a, Monad m) => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) forall a (m :: * -> *). (Data a, MonadPlus m) => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) forall a (c :: * -> *). Data a => (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Paginated a) forall a (c :: * -> *). Data a => (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Paginated a -> c (Paginated a) forall a (t :: * -> *) (c :: * -> *). (Data a, Typeable t) => (forall d. Data d => c (t d)) -> Maybe (c (Paginated a)) forall a (t :: * -> * -> *) (c :: * -> *). (Data a, Typeable t) => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Paginated a)) forall a. Typeable a -> (forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> a -> c a) -> (forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c a) -> (a -> Constr) -> (a -> DataType) -> (forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c a)) -> (forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a)) -> ((forall b. Data b => b -> b) -> a -> a) -> (forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r) -> (forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r) -> (forall u. (forall d. Data d => d -> u) -> a -> [u]) -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u) -> (forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> a -> m a) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a) -> Data a forall u. Int -> (forall d. Data d => d -> u) -> Paginated a -> u forall u. (forall d. Data d => d -> u) -> Paginated a -> [u] forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Paginated a) forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Paginated a -> c (Paginated a) forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Paginated a)) forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Paginated a)) $cPaginated :: Constr $tPaginated :: DataType gmapMo :: (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) $cgmapMo :: forall a (m :: * -> *). (Data a, MonadPlus m) => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) gmapMp :: (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) $cgmapMp :: forall a (m :: * -> *). (Data a, MonadPlus m) => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) gmapM :: (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) $cgmapM :: forall a (m :: * -> *). (Data a, Monad m) => (forall d. Data d => d -> m d) -> Paginated a -> m (Paginated a) gmapQi :: Int -> (forall d. Data d => d -> u) -> Paginated a -> u $cgmapQi :: forall a u. Data a => Int -> (forall d. Data d => d -> u) -> Paginated a -> u gmapQ :: (forall d. Data d => d -> u) -> Paginated a -> [u] $cgmapQ :: forall a u. Data a => (forall d. Data d => d -> u) -> Paginated a -> [u] gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r $cgmapQr :: forall a r r'. Data a => (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r $cgmapQl :: forall a r r'. Data a => (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Paginated a -> r gmapT :: (forall b. Data b => b -> b) -> Paginated a -> Paginated a $cgmapT :: forall a. Data a => (forall b. Data b => b -> b) -> Paginated a -> Paginated a dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Paginated a)) $cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *). (Data a, Typeable t) => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Paginated a)) dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c (Paginated a)) $cdataCast1 :: forall a (t :: * -> *) (c :: * -> *). (Data a, Typeable t) => (forall d. Data d => c (t d)) -> Maybe (c (Paginated a)) dataTypeOf :: Paginated a -> DataType $cdataTypeOf :: forall a. Data a => Paginated a -> DataType toConstr :: Paginated a -> Constr $ctoConstr :: forall a. Data a => Paginated a -> Constr gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Paginated a) $cgunfold :: forall a (c :: * -> *). Data a => (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Paginated a) gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Paginated a -> c (Paginated a) $cgfoldl :: forall a (c :: * -> *). Data a => (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Paginated a -> c (Paginated a) $cp1Data :: forall a. Data a => Typeable (Paginated a) Data, Typeable, (forall x. Paginated a -> Rep (Paginated a) x) -> (forall x. Rep (Paginated a) x -> Paginated a) -> Generic (Paginated a) forall x. Rep (Paginated a) x -> Paginated a forall x. Paginated a -> Rep (Paginated a) x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a forall a x. Rep (Paginated a) x -> Paginated a forall a x. Paginated a -> Rep (Paginated a) x $cto :: forall a x. Rep (Paginated a) x -> Paginated a $cfrom :: forall a x. Paginated a -> Rep (Paginated a) x Generic, a -> Paginated b -> Paginated a (a -> b) -> Paginated a -> Paginated b (forall a b. (a -> b) -> Paginated a -> Paginated b) -> (forall a b. a -> Paginated b -> Paginated a) -> Functor Paginated forall a b. a -> Paginated b -> Paginated a forall a b. (a -> b) -> Paginated a -> Paginated b forall (f :: * -> *). (forall a b. (a -> b) -> f a -> f b) -> (forall a b. a -> f b -> f a) -> Functor f <$ :: a -> Paginated b -> Paginated a $c<$ :: forall a b. a -> Paginated b -> Paginated a fmap :: (a -> b) -> Paginated a -> Paginated b $cfmap :: forall a b. (a -> b) -> Paginated a -> Paginated b Functor) instance NFData a => NFData (Paginated a) instance Foldable Paginated where foldr :: (a -> b -> b) -> b -> Paginated a -> b foldr a -> b -> b f b x = (a -> b -> b) -> b -> [a] -> b forall (t :: * -> *) a b. Foldable t => (a -> b -> b) -> b -> t a -> b foldr a -> b -> b f b x ([a] -> b) -> (Paginated a -> [a]) -> Paginated a -> b forall b c a. (b -> c) -> (a -> b) -> a -> c . Paginated a -> [a] forall a. Paginated a -> [a] pgItems instance Traversable Paginated where traverse :: (a -> f b) -> Paginated a -> f (Paginated b) traverse a -> f b f Paginated a p = let g :: Paginated a -> [a] -> Paginated a g Paginated a p' [a] xs = Paginated a p' {pgItems :: [a] pgItems = [a] xs} in Paginated a -> [b] -> Paginated b forall a a. Paginated a -> [a] -> Paginated a g Paginated a p ([b] -> Paginated b) -> f [b] -> f (Paginated b) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> (a -> f b) -> [a] -> f [b] forall (t :: * -> *) (f :: * -> *) a b. (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b) traverse a -> f b f (Paginated a -> [a] forall a. Paginated a -> [a] pgItems Paginated a p) -- | Create paginated data. paginate :: (Functor m, Integral n) => -- | Pagination options Pagination -> -- | Total number of items Natural -> -- | The element producing callback. The function takes arguments: -- offset and limit. (n -> n -> m [a]) -> -- | The paginated data m (Paginated a) paginate :: Pagination -> Natural -> (n -> n -> m [a]) -> m (Paginated a) paginate (Pagination Natural size Natural index') Natural totalItems n -> n -> m [a] f = [a] -> Paginated a forall a. [a] -> Paginated a r ([a] -> Paginated a) -> m [a] -> m (Paginated a) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> n -> n -> m [a] f (Natural -> n forall a b. (Integral a, Num b) => a -> b fromIntegral Natural offset) (Natural -> n forall a b. (Integral a, Num b) => a -> b fromIntegral Natural size) where r :: [a] -> Paginated a r [a] xs = Paginated :: forall a. [a] -> Pagination -> Natural -> Natural -> Paginated a Paginated { pgItems :: [a] pgItems = [a] xs, pgPagination :: Pagination pgPagination = Natural -> Natural -> Pagination Pagination Natural size Natural index, pgPagesTotal :: Natural pgPagesTotal = Natural totalPages, pgItemsTotal :: Natural pgItemsTotal = Natural totalItems } (Natural whole, Natural rems) = Natural totalItems Natural -> Natural -> (Natural, Natural) forall a. Integral a => a -> a -> (a, a) `quotRem` Natural size totalPages :: Natural totalPages = Natural -> Natural -> Natural forall a. Ord a => a -> a -> a max Natural 1 (Natural whole Natural -> Natural -> Natural forall a. Num a => a -> a -> a + if Natural rems Natural -> Natural -> Bool forall a. Eq a => a -> a -> Bool == Natural 0 then Natural 0 else Natural 1) index :: Natural index = Natural -> Natural -> Natural forall a. Ord a => a -> a -> a min Natural index' Natural totalPages offset :: Natural offset = (Natural index Natural -> Natural -> Natural forall a. Num a => a -> a -> a - Natural 1) Natural -> Natural -> Natural forall a. Num a => a -> a -> a * Natural size -- | Get subset of items for current page. paginatedItems :: Paginated a -> [a] paginatedItems :: Paginated a -> [a] paginatedItems = Paginated a -> [a] forall a. Paginated a -> [a] pgItems -- | Get 'Pagination' parameters that were used to create this paginated -- result. paginatedPagination :: Paginated a -> Pagination paginatedPagination :: Paginated a -> Pagination paginatedPagination = Paginated a -> Pagination forall a. Paginated a -> Pagination pgPagination -- | Get the total number of pages in this collection. paginatedPagesTotal :: Paginated a -> Natural paginatedPagesTotal :: Paginated a -> Natural paginatedPagesTotal = Paginated a -> Natural forall a. Paginated a -> Natural pgPagesTotal -- | Get the total number of items in this collection. paginatedItemsTotal :: Paginated a -> Natural paginatedItemsTotal :: Paginated a -> Natural paginatedItemsTotal = Paginated a -> Natural forall a. Paginated a -> Natural pgItemsTotal -- | Test whether there are other pages. hasOtherPages :: Paginated a -> Bool hasOtherPages :: Paginated a -> Bool hasOtherPages Paginated {Natural [a] Pagination pgItemsTotal :: Natural pgPagesTotal :: Natural pgPagination :: Pagination pgItems :: [a] pgItemsTotal :: forall a. Paginated a -> Natural pgPagesTotal :: forall a. Paginated a -> Natural pgPagination :: forall a. Paginated a -> Pagination pgItems :: forall a. Paginated a -> [a] ..} = Natural pgPagesTotal Natural -> Natural -> Bool forall a. Ord a => a -> a -> Bool > Natural 1 -- | Is there previous page? hasPrevPage :: Paginated a -> Bool hasPrevPage :: Paginated a -> Bool hasPrevPage Paginated {Natural [a] Pagination pgItemsTotal :: Natural pgPagesTotal :: Natural pgPagination :: Pagination pgItems :: [a] pgItemsTotal :: forall a. Paginated a -> Natural pgPagesTotal :: forall a. Paginated a -> Natural pgPagination :: forall a. Paginated a -> Pagination pgItems :: forall a. Paginated a -> [a] ..} = Pagination -> Natural pageIndex Pagination pgPagination Natural -> Natural -> Bool forall a. Ord a => a -> a -> Bool > Natural 1 -- | Is there next page? hasNextPage :: Paginated a -> Bool hasNextPage :: Paginated a -> Bool hasNextPage Paginated {Natural [a] Pagination pgItemsTotal :: Natural pgPagesTotal :: Natural pgPagination :: Pagination pgItems :: [a] pgItemsTotal :: forall a. Paginated a -> Natural pgPagesTotal :: forall a. Paginated a -> Natural pgPagination :: forall a. Paginated a -> Pagination pgItems :: forall a. Paginated a -> [a] ..} = Pagination -> Natural pageIndex Pagination pgPagination Natural -> Natural -> Bool forall a. Ord a => a -> a -> Bool < Natural pgPagesTotal -- | Get range of pages to show before and after the current page. This does -- not necessarily include the first and the last pages (they are supposed -- to be shown in all cases). Result of the function is always sorted. pageRange :: -- | Paginated data Paginated a -> -- | Number of pages to show before and after Natural -> -- | Page range NonEmpty Natural pageRange :: Paginated a -> Natural -> NonEmpty Natural pageRange Paginated {Natural [a] Pagination pgItemsTotal :: Natural pgPagesTotal :: Natural pgPagination :: Pagination pgItems :: [a] pgItemsTotal :: forall a. Paginated a -> Natural pgPagesTotal :: forall a. Paginated a -> Natural pgPagination :: forall a. Paginated a -> Pagination pgItems :: forall a. Paginated a -> [a] ..} Natural 0 = [Natural] -> NonEmpty Natural forall a. [a] -> NonEmpty a NE.fromList [Pagination -> Natural pageIndex Pagination pgPagination] pageRange Paginated {Natural [a] Pagination pgItemsTotal :: Natural pgPagesTotal :: Natural pgPagination :: Pagination pgItems :: [a] pgItemsTotal :: forall a. Paginated a -> Natural pgPagesTotal :: forall a. Paginated a -> Natural pgPagination :: forall a. Paginated a -> Pagination pgItems :: forall a. Paginated a -> [a] ..} Natural n = let len :: Natural len = Natural -> Natural -> Natural forall a. Ord a => a -> a -> a min Natural pgPagesTotal (Natural n Natural -> Natural -> Natural forall a. Num a => a -> a -> a * Natural 2 Natural -> Natural -> Natural forall a. Num a => a -> a -> a + Natural 1) index :: Natural index = Pagination -> Natural pageIndex Pagination pgPagination shift :: Natural shift | Natural index Natural -> Natural -> Bool forall a. Ord a => a -> a -> Bool <= Natural n = Natural 0 | Natural index Natural -> Natural -> Bool forall a. Ord a => a -> a -> Bool >= Natural pgPagesTotal Natural -> Natural -> Natural forall a. Num a => a -> a -> a - Natural n = Natural pgPagesTotal Natural -> Natural -> Natural forall a. Num a => a -> a -> a - Natural len | Bool otherwise = Natural index Natural -> Natural -> Natural forall a. Num a => a -> a -> a - Natural n Natural -> Natural -> Natural forall a. Num a => a -> a -> a - Natural 1 in (Natural -> Natural -> Natural forall a. Num a => a -> a -> a + Natural shift) (Natural -> Natural) -> NonEmpty Natural -> NonEmpty Natural forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> [Natural] -> NonEmpty Natural forall a. [a] -> NonEmpty a NE.fromList [Natural 1 .. Natural len] -- | Backward ellipsis appears when page range (pages around current page to -- jump to) has gap between its beginning and the first page. backwardEllip :: -- | Paginated data Paginated a -> -- | Number of pages to show before and after Natural -> Bool backwardEllip :: Paginated a -> Natural -> Bool backwardEllip Paginated a p Natural n = NonEmpty Natural -> Natural forall a. NonEmpty a -> a NE.head (Paginated a -> Natural -> NonEmpty Natural forall a. Paginated a -> Natural -> NonEmpty Natural pageRange Paginated a p Natural n) Natural -> Natural -> Bool forall a. Ord a => a -> a -> Bool > Natural 2 -- | Forward ellipsis appears when page range (pages around current page to -- jump to) has gap between its end and the last page. forwardEllip :: -- | Paginated data Paginated a -> -- | Number of pages to show before and after Natural -> -- | Do we have forward ellipsis? Bool forwardEllip :: Paginated a -> Natural -> Bool forwardEllip p :: Paginated a p@Paginated {Natural [a] Pagination pgItemsTotal :: Natural pgPagesTotal :: Natural pgPagination :: Pagination pgItems :: [a] pgItemsTotal :: forall a. Paginated a -> Natural pgPagesTotal :: forall a. Paginated a -> Natural pgPagination :: forall a. Paginated a -> Pagination pgItems :: forall a. Paginated a -> [a] ..} Natural n = NonEmpty Natural -> Natural forall a. NonEmpty a -> a NE.last (Paginated a -> Natural -> NonEmpty Natural forall a. Paginated a -> Natural -> NonEmpty Natural pageRange Paginated a p Natural n) Natural -> Natural -> Bool forall a. Ord a => a -> a -> Bool < Natural -> Natural forall a. Enum a => a -> a pred Natural pgPagesTotal ---------------------------------------------------------------------------- -- Exceptions -- | Exception indicating various problems when working with paginated data. data PaginationException = -- | Page size (number of items per page) was zero ZeroPageSize | -- | Page index was zero (they start from one) ZeroPageIndex deriving (PaginationException -> PaginationException -> Bool (PaginationException -> PaginationException -> Bool) -> (PaginationException -> PaginationException -> Bool) -> Eq PaginationException forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: PaginationException -> PaginationException -> Bool $c/= :: PaginationException -> PaginationException -> Bool == :: PaginationException -> PaginationException -> Bool $c== :: PaginationException -> PaginationException -> Bool Eq, Int -> PaginationException -> ShowS [PaginationException] -> ShowS PaginationException -> String (Int -> PaginationException -> ShowS) -> (PaginationException -> String) -> ([PaginationException] -> ShowS) -> Show PaginationException forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [PaginationException] -> ShowS $cshowList :: [PaginationException] -> ShowS show :: PaginationException -> String $cshow :: PaginationException -> String showsPrec :: Int -> PaginationException -> ShowS $cshowsPrec :: Int -> PaginationException -> ShowS Show, Typeable PaginationException DataType Constr Typeable PaginationException -> (forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> PaginationException -> c PaginationException) -> (forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c PaginationException) -> (PaginationException -> Constr) -> (PaginationException -> DataType) -> (forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c PaginationException)) -> (forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PaginationException)) -> ((forall b. Data b => b -> b) -> PaginationException -> PaginationException) -> (forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> PaginationException -> r) -> (forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> PaginationException -> r) -> (forall u. (forall d. Data d => d -> u) -> PaginationException -> [u]) -> (forall u. Int -> (forall d. Data d => d -> u) -> PaginationException -> u) -> (forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException) -> Data PaginationException PaginationException -> DataType PaginationException -> Constr (forall b. Data b => b -> b) -> PaginationException -> PaginationException (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> PaginationException -> c PaginationException (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c PaginationException forall a. Typeable a -> (forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> a -> c a) -> (forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c a) -> (a -> Constr) -> (a -> DataType) -> (forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c a)) -> (forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a)) -> ((forall b. Data b => b -> b) -> a -> a) -> (forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r) -> (forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r) -> (forall u. (forall d. Data d => d -> u) -> a -> [u]) -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u) -> (forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> a -> m a) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a) -> (forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a) -> Data a forall u. Int -> (forall d. Data d => d -> u) -> PaginationException -> u forall u. (forall d. Data d => d -> u) -> PaginationException -> [u] forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> PaginationException -> r forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> PaginationException -> r forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c PaginationException forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> PaginationException -> c PaginationException forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c PaginationException) forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PaginationException) $cZeroPageIndex :: Constr $cZeroPageSize :: Constr $tPaginationException :: DataType gmapMo :: (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException $cgmapMo :: forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException gmapMp :: (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException $cgmapMp :: forall (m :: * -> *). MonadPlus m => (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException gmapM :: (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException $cgmapM :: forall (m :: * -> *). Monad m => (forall d. Data d => d -> m d) -> PaginationException -> m PaginationException gmapQi :: Int -> (forall d. Data d => d -> u) -> PaginationException -> u $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PaginationException -> u gmapQ :: (forall d. Data d => d -> u) -> PaginationException -> [u] $cgmapQ :: forall u. (forall d. Data d => d -> u) -> PaginationException -> [u] gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> PaginationException -> r $cgmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> PaginationException -> r gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> PaginationException -> r $cgmapQl :: forall r r'. (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> PaginationException -> r gmapT :: (forall b. Data b => b -> b) -> PaginationException -> PaginationException $cgmapT :: (forall b. Data b => b -> b) -> PaginationException -> PaginationException dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PaginationException) $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *). Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PaginationException) dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c PaginationException) $cdataCast1 :: forall (t :: * -> *) (c :: * -> *). Typeable t => (forall d. Data d => c (t d)) -> Maybe (c PaginationException) dataTypeOf :: PaginationException -> DataType $cdataTypeOf :: PaginationException -> DataType toConstr :: PaginationException -> Constr $ctoConstr :: PaginationException -> Constr gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c PaginationException $cgunfold :: forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c PaginationException gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> PaginationException -> c PaginationException $cgfoldl :: forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> PaginationException -> c PaginationException $cp1Data :: Typeable PaginationException Data, Typeable, (forall x. PaginationException -> Rep PaginationException x) -> (forall x. Rep PaginationException x -> PaginationException) -> Generic PaginationException forall x. Rep PaginationException x -> PaginationException forall x. PaginationException -> Rep PaginationException x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep PaginationException x -> PaginationException $cfrom :: forall x. PaginationException -> Rep PaginationException x Generic) instance NFData PaginationException instance Exception PaginationException