postgis-trivial-0.0.1.0: src/Database/Postgis/Trivial/Cast.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
module Database.Postgis.Trivial.Cast where
import GHC.Base hiding ( foldr )
import GHC.Num ( Num((+)) )
import Control.Monad ( replicateM, mapM_ )
import Data.Functor ( (<$>), (<&>) )
import Data.Typeable ( Typeable )
import Data.Foldable ( Foldable(..) )
import Data.Traversable ( Traversable(..) )
import qualified Data.Vector as V
import qualified Data.Map as M
import qualified Data.IntMap as IM
import Data.List (zip)
import Database.Postgis.Trivial.Types
import Database.Postgis.Trivial.Internal
-- | 'Type cast' type family
type family Cast p
-- | 'Type cast' procedures
class (Typeable p, PointND (Cast p)) => Castable p where
toPointND :: p -> Cast p
fromPointND :: Cast p -> p
-- | Translator of Traversables
class (Castable p, Traversable t, Typeable t) => Trans t p where
transTo :: t p -> t (Cast p)
transTo vs = toPointND <$> vs
transFrom :: t (Cast p) -> t p
transFrom vs = fromPointND <$> vs
instance Castable p => Trans [] p where
instance Castable p => Trans V.Vector p where
instance (Castable p, Typeable k) => Trans (M.Map k) p where
instance Castable p => Trans IM.IntMap p where
-- | Replication procedure for different Traversables
class (Traversable t, Typeable t) => Repl t b where
repl :: Int -> HeaderGetter b -> HeaderGetter (t b)
instance Repl [] b where
repl = replicateM
instance Repl V.Vector b where
repl = V.replicateM
-- | Point chain is a base structural component of geometries
class Traversable t => GeoChain t where
count :: t p -> Int
putChain :: PointND a => Putter (t a)
putChain vs = do
putChainLen $ count vs
mapM_ putPointND vs
getChain :: (Traversable t, PointND a) => HeaderGetter (t a)
-- {-# MINIMAL count | putChain #-}
instance GeoChain V.Vector where
count = V.length
getChain = getChainLen >>= (`V.replicateM` getPointND)
instance GeoChain [] where
count = foldr (\_ r->r+1) (0::Int)
getChain = getChainLen >>= (`replicateM` getPointND)
instance GeoChain (M.Map Int) where
count = M.size
getChain = (getChainLen >>= (`replicateM` getPointND)) <&>
(M.fromList . zip ([0..]::[Int]))
instance GeoChain IM.IntMap where
count = IM.size
getChain = (getChainLen >>= (`replicateM` getPointND)) <&>
(IM.fromList . zip ([0..]::[Int]))