indexation (empty) → 0.1
raw patch · 17 files changed
+650/−0 lines, 17 filesdep +basedep +bytestringdep +cerealsetup-changed
Dependencies added: base, bytestring, cereal, deferred-folds, focus, foldl, hashable, list-t, potoki-cereal, potoki-core, profunctors, stm-containers, transformers, unordered-containers, vector
Files
- LICENSE +22/−0
- Setup.hs +2/−0
- indexation.cabal +74/−0
- library/Indexation/Cereal/Get.hs +49/−0
- library/Indexation/Cereal/Put.hs +45/−0
- library/Indexation/EntityTable.hs +31/−0
- library/Indexation/Folds.hs +46/−0
- library/Indexation/HashMap.hs +13/−0
- library/Indexation/IO.hs +65/−0
- library/Indexation/Index.hs +9/−0
- library/Indexation/IndexTable.hs +40/−0
- library/Indexation/Instances/Cereal.hs +13/−0
- library/Indexation/Potoki/Fetch.hs +36/−0
- library/Indexation/Potoki/Transform.hs +12/−0
- library/Indexation/Prelude.hs +124/−0
- library/Indexation/Types.hs +14/−0
- library/Indexation/Vector.hs +55/−0
+ LICENSE view
@@ -0,0 +1,22 @@+Copyright (c) 2018, Metrix.AI++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ indexation.cabal view
@@ -0,0 +1,74 @@+name:+ indexation+version:+ 0.1+category:+ Data+synopsis:+ Tools for entity indexation+description:+ A set of tools for indexing entities+homepage:+ https://github.com/nikita-volkov/indexation +bug-reports:+ https://github.com/nikita-volkov/indexation/issues +author:+ Nikita Volkov <nikita.y.volkov@mail.ru>+maintainer:+ Metrix Ninjas <ninjas@metrix.ai>+copyright:+ (c) 2018, Metrix.AI+license:+ MIT+license-file:+ LICENSE+build-type:+ Simple+cabal-version:+ >=1.10++source-repository head+ type:+ git+ location:+ git://github.com/nikita-volkov/indexation.git++library+ hs-source-dirs:+ library+ default-extensions:+ Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, PatternSynonyms, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeApplications, TypeFamilies, TypeOperators, UnboxedTuples+ default-language:+ Haskell2010+ exposed-modules:+ Indexation.Index+ Indexation.IndexTable+ Indexation.EntityTable+ Indexation.IO+ Indexation.Folds+ other-modules:+ Indexation.Instances.Cereal+ Indexation.Potoki.Fetch+ Indexation.Potoki.Transform+ Indexation.Types+ Indexation.Cereal.Get+ Indexation.Cereal.Put+ Indexation.Prelude+ Indexation.Vector+ Indexation.HashMap+ build-depends:+ base >=4.7 && <5,+ bytestring >=0.10.8 && <0.11,+ cereal >=0.5.5 && <0.6,+ deferred-folds >=0.4.1 && <0.5,+ focus >=0.1.5.2 && <0.2,+ foldl >=1 && <2,+ hashable >=1 && <2,+ list-t >=1 && <1.1,+ potoki-cereal >=0.2.1.1 && <0.3,+ potoki-core >=2.2 && <2.3,+ profunctors >=5.2 && <6,+ stm-containers >=0.2.16 && <0.3,+ transformers >=0.4 && <0.6,+ unordered-containers >=0.2.9 && <0.3,+ vector >=0.12 && <0.13
+ library/Indexation/Cereal/Get.hs view
@@ -0,0 +1,49 @@+module Indexation.Cereal.Get+where++import Indexation.Prelude+import Indexation.Types+import Data.Serialize.Get+import qualified Data.HashMap.Strict as A+import qualified Indexation.HashMap as A+import qualified Data.Vector as B+++getIndexHashMap :: (Eq k, Hashable k) => Get k -> Get (HashMap k Int)+getIndexHashMap getKey =+ getSize >>= getAssociations+ where+ getSize = getInt64le+ getAssociations size = foldM step A.empty (enumFromTo 0 (pred (fromIntegral size)))+ where+ step hashMap index = do+ key <- getKey+ return (A.insert key index hashMap)++getIndexTableAsEntityTable :: (Eq entity, Hashable entity) => Get entity -> Get (IndexTable entity)+getIndexTableAsEntityTable getEntity =+ do+ size <- getSize+ associations <- getAssociations size+ return (IndexTable size associations)+ where+ getSize = fromIntegral <$> getInt64le+ getAssociations size = foldM step A.empty (enumFromTo 0 (pred size))+ where+ step hashMap index = do+ entity <- getEntity+ return (A.insert entity index hashMap)++getVector :: Get element -> Get (Vector element)+getVector getElement =+ getSize >>= getElements+ where+ getSize = getInt64le+ getElements size = B.replicateM (fromIntegral size) getElement++getEntityTable :: Get entity -> Get (EntityTable entity)+getEntityTable getEntity =+ EntityTable <$> getVector getEntity++getIndex :: Get (Index entity)+getIndex = Index . fromIntegral <$> getInt64le
+ library/Indexation/Cereal/Put.hs view
@@ -0,0 +1,45 @@+module Indexation.Cereal.Put+where++import Indexation.Prelude+import Indexation.Types+import Data.Serialize.Put+import qualified Data.HashMap.Strict as A+import qualified Indexation.HashMap as A+import qualified Data.Vector as B+++putHashMapWithSize :: Putter k -> Putter v -> Putter (HashMap k v)+putHashMapWithSize keyPutter valuePutter hashMap =+ size *> associations+ where+ size = putInt64le (fromIntegral (A.size hashMap))+ associations = A.traverse_ association hashMap+ association key value = keyPutter key *> valuePutter value++putVector :: Putter element -> Putter (Vector element)+putVector putElement vector =+ putSize *> putElements+ where+ putSize = putInt64le (fromIntegral (B.length vector))+ putElements = traverse_ putElement vector++{-|+It's recommended to use 'putIndexTableAsEntityTable' instead.+The hashmap traversal implementation is inefficient and+the representation of 'EntityTable' is more compact.+-}+putIndexTableDirectly :: Putter entity -> Putter (IndexTable entity)+putIndexTableDirectly putEntity (IndexTable size hashMap) =+ putSize *> putAssociations+ where+ putSize = putInt64le (fromIntegral size)+ putAssociations = A.traverse_ putAssociation hashMap+ putAssociation key entity = putEntity key *> putInt64le (fromIntegral entity)++putEntityTable :: Putter entity -> Putter (EntityTable entity)+putEntityTable putEntity (EntityTable vector) =+ putVector putEntity vector++putIndex :: Putter (Index entity)+putIndex (Index int) = putInt64le (fromIntegral int)
+ library/Indexation/EntityTable.hs view
@@ -0,0 +1,31 @@+module Indexation.EntityTable+(+ EntityTable,+ indexTable,+ lookup,+)+where++import Indexation.Prelude hiding (lookup)+import Indexation.Types+import qualified Indexation.Vector as A+import qualified Data.Vector as B+import qualified Indexation.Cereal.Put as C+import qualified Indexation.Cereal.Get as D+import qualified Data.Serialize as E+++instance E.Serialize entity => E.Serialize (EntityTable entity) where+ put = C.putEntityTable E.put+ get = D.getEntityTable E.get++indexTable :: IndexTable entity -> EntityTable entity+indexTable (IndexTable size table) =+ EntityTable vector+ where+ vector =+ A.indexHashMapWithSize size table++lookup :: Index entity -> EntityTable entity -> Maybe entity+lookup (Index indexPrim) (EntityTable vector) =+ vector B.!? indexPrim
+ library/Indexation/Folds.hs view
@@ -0,0 +1,46 @@+module Indexation.Folds+where++import Indexation.Prelude+import Indexation.Types+import Control.Foldl+import qualified Data.HashMap.Strict as B+import qualified Data.Serialize as C+import qualified Data.ByteString as D+++indexTable :: (Eq entity, Hashable entity) => Fold entity (IndexTable entity)+indexTable =+ Fold step init extract+ where+ init = IndexTable 0 B.empty+ step (IndexTable index map) key =+ case B.lookup key map of+ Just _ -> IndexTable index map+ Nothing -> let+ newMap = B.insert key index map+ newIndex = succ index+ in IndexTable newIndex newMap+ extract = id++serializeToFile :: Serialize entity => FilePath -> FoldM IO entity (Either IOException ())+serializeToFile filePath =+ lmap C.encode (writeBytesToFile filePath)++writeBytesToFile :: FilePath -> FoldM IO ByteString (Either IOException ())+writeBytesToFile filePath =+ FoldM step init exit+ where+ step :: Either IOException Handle -> ByteString -> IO (Either IOException Handle)+ step errorOrFileHandle bytes =+ case errorOrFileHandle of+ Right fileHandle -> try (D.hPut fileHandle bytes $> fileHandle)+ Left exception -> return (Left exception)+ init :: IO (Either IOException Handle)+ init =+ try (openFile filePath WriteMode)+ exit :: Either IOException Handle -> IO (Either IOException ())+ exit errorOrFileHandle =+ case errorOrFileHandle of+ Right fileHandle -> try (hClose fileHandle)+ Left exception -> return (Left exception)
+ library/Indexation/HashMap.hs view
@@ -0,0 +1,13 @@+module Indexation.HashMap+where++import Indexation.Prelude+import Data.HashMap.Strict+++traverse_ :: Applicative effect => (k -> v -> effect ()) -> HashMap k v -> effect ()+traverse_ effect =+ foldrWithKey step init+ where+ init = pure ()+ step k v acc = effect k v *> acc
+ library/Indexation/IO.hs view
@@ -0,0 +1,65 @@+module Indexation.IO+(+ indexProduceToFiles,+ readEntitiesAmountFromEntityTableFile,+)+where++import Indexation.Prelude+import Indexation.Types+import Indexation.Instances.Cereal ()+import qualified Potoki.Core.IO as PotokiIo+import qualified Potoki.Core.Consume as PotokiConsume+import qualified Potoki.Cereal.Consume as PotokiConsume+import qualified Potoki.Cereal.Produce as PotokiProduce+import qualified Indexation.Potoki.Transform as PotokiTransform+import qualified Indexation.Vector as Vector+import qualified STMContainers.Map as StmMap+import qualified Data.Serialize as Cereal+import qualified Data.ByteString as ByteString+++createIndexer :: IO (Indexer entity)+createIndexer = do+ sizeVar <- newTVarIO 0+ map <- StmMap.newIO+ return (Indexer sizeVar map)++createIndexerVector :: Indexer entity -> IO (Vector entity)+createIndexerVector (Indexer sizeVar map) =+ atomically $ do+ size <- readTVar sizeVar+ Vector.listT size (fmap swap (StmMap.stream map))++createIndexerEntityTable :: Indexer entity -> IO (EntityTable entity)+createIndexerEntityTable = fmap EntityTable . createIndexerVector++serializeProduceEntityIndicesToFile :: (Eq entity, Hashable entity) => FilePath -> Indexer entity -> Produce entity -> IO (Either IOException ())+serializeProduceEntityIndicesToFile path indexer entityProduce =+ PotokiIo.produceAndConsume entityProduce $+ PotokiConsume.transform (PotokiTransform.indexConcurrently indexer) $+ PotokiConsume.encodeToFile path++serializeIndexerToFile :: Serialize entity => FilePath -> Indexer entity -> IO (Either IOException ())+serializeIndexerToFile path indexer = do+ entityTable <- createIndexerEntityTable indexer+ let+ produce = PotokiProduce.put (Cereal.put entityTable)+ consume = PotokiConsume.writeBytesToFile path+ in PotokiIo.produceAndConsume produce consume++indexProduceToFiles :: (Eq entity, Hashable entity, Serialize entity) => FilePath {-^ Entity table -} -> FilePath {-^ Index stream -} -> Produce entity -> IO (Either IOException ())+indexProduceToFiles entityTablePath indexStreamPath entityProduce =+ do+ indexer <- createIndexer+ runExceptT $ do+ ExceptT (serializeProduceEntityIndicesToFile indexStreamPath indexer entityProduce)+ ExceptT (serializeIndexerToFile entityTablePath indexer)++readEntitiesAmountFromEntityTableFile :: FilePath -> IO (Either IOException Int)+readEntitiesAmountFromEntityTableFile filePath =+ try $ do+ bytes <- withFile filePath ReadMode (flip ByteString.hGet 4)+ Cereal.runGet Cereal.getInt64le bytes & \ case+ Right x -> return (fromIntegral x)+ Left x -> error ("Unexpected binary parsing error: " <> x)
+ library/Indexation/Index.hs view
@@ -0,0 +1,9 @@+module Indexation.Index+(+ Index(..),+)+where++import Indexation.Prelude+import Indexation.Types+import Indexation.Instances.Cereal
+ library/Indexation/IndexTable.hs view
@@ -0,0 +1,40 @@+module Indexation.IndexTable+(+ IndexTable,+ lookup,+ register,+ empty,+)+where++import Indexation.Prelude hiding (lookup, empty)+import Indexation.Types+import qualified Data.HashMap.Strict as A+import qualified Indexation.Cereal.Get as B+import qualified Indexation.Cereal.Put as C+import qualified Indexation.EntityTable as D+import qualified Data.Serialize as E+++instance (E.Serialize entity, Eq entity, Hashable entity) => E.Serialize (IndexTable entity) where+ put = C.putEntityTable E.put . D.indexTable+ get = B.getIndexTableAsEntityTable E.get++lookup :: (Eq entity, Hashable entity) => entity -> IndexTable entity -> Maybe (Index entity)+lookup entity (IndexTable size hashMap) =+ fmap Index (A.lookup entity hashMap)++register :: (Eq entity, Hashable entity) => entity -> IndexTable entity -> (Index entity, IndexTable entity)+register entity (IndexTable size hashMap) =+ A.lookup entity hashMap & \ case+ Just index -> (Index index, IndexTable size hashMap)+ Nothing -> let+ newSize = succ size+ newHashMap = A.insert entity size hashMap+ index = Index size+ newTable = IndexTable newSize newHashMap+ in (index, newTable)++empty :: (Eq entity, Hashable entity) => IndexTable entity+empty =+ IndexTable 0 mempty
+ library/Indexation/Instances/Cereal.hs view
@@ -0,0 +1,13 @@+module Indexation.Instances.Cereal+where++import Indexation.Prelude+import Indexation.Types+import Data.Serialize+import qualified Indexation.Cereal.Get as Get+import qualified Indexation.Cereal.Put as Put+++instance Serialize (Index a) where+ get = Get.getIndex+ put = Put.putIndex
+ library/Indexation/Potoki/Fetch.hs view
@@ -0,0 +1,36 @@+module Indexation.Potoki.Fetch where++import Indexation.Prelude+import Indexation.Types+import Potoki.Core.Fetch+import qualified Indexation.IndexTable as A+import qualified STMContainers.Map as B+import qualified Focus as C+++index :: (Eq entity, Hashable entity) => IORef (IndexTable entity) -> Fetch entity -> Fetch (Index entity)+index indexTableRef (Fetch entityMaybeIO) =+ Fetch $ do+ entityMaybe <- entityMaybeIO+ case entityMaybe of+ Just entity -> do+ indexTable <- readIORef indexTableRef+ A.register entity indexTable & \ (!index, !newIndexTable) -> do+ writeIORef indexTableRef newIndexTable+ return (Just index)+ Nothing -> return Nothing++indexConcurrently :: (Eq entity, Hashable entity) => Indexer entity -> Fetch entity -> Fetch (Index entity)+indexConcurrently (Indexer sizeVar map) (Fetch entityMaybeIO) =+ Fetch $ do+ entityMaybe <- entityMaybeIO+ case entityMaybe of+ Just entity -> fmap Just $ atomically $ B.focus strategy entity map+ Nothing -> return Nothing+ where+ strategy = \ case+ Just indexInt -> return (Index indexInt, C.Keep)+ Nothing -> do+ size <- readTVar sizeVar+ writeTVar sizeVar $! succ size+ return (Index size, C.Replace size)
+ library/Indexation/Potoki/Transform.hs view
@@ -0,0 +1,12 @@+module Indexation.Potoki.Transform where++import Indexation.Prelude hiding (runState)+import Indexation.Types+import Potoki.Core.Transform+import qualified Indexation.Potoki.Fetch as A+import qualified Indexation.IndexTable as B+import qualified STMContainers.Map as C+++indexConcurrently :: (Eq entity, Hashable entity) => Indexer entity -> Transform entity (Index entity)+indexConcurrently indexer = Transform (return . A.indexConcurrently indexer)
+ library/Indexation/Prelude.hs view
@@ -0,0 +1,124 @@+module Indexation.Prelude+(+ module Exports,+)+where+++-- base+-------------------------+import Control.Applicative as Exports+import Control.Arrow as Exports+import Control.Category as Exports+import Control.Concurrent as Exports+import Control.Exception as Exports+import Control.Monad as Exports hiding (mapM_, sequence_, forM_, msum, mapM, sequence, forM)+import Control.Monad.IO.Class as Exports+import Control.Monad.Fix as Exports hiding (fix)+import Control.Monad.ST as Exports+import Data.Bits as Exports+import Data.Bool as Exports+import Data.Char as Exports+import Data.Coerce as Exports+import Data.Complex as Exports+import Data.Data as Exports+import Data.Dynamic as Exports+import Data.Either as Exports+import Data.Fixed as Exports+import Data.Foldable as Exports+import Data.Function as Exports hiding (id, (.))+import Data.Functor as Exports+import Data.Int as Exports+import Data.IORef as Exports+import Data.Ix as Exports+import Data.List as Exports hiding (sortOn, isSubsequenceOf, uncons, concat, foldr, foldl1, maximum, minimum, product, sum, all, and, any, concatMap, elem, foldl, foldr1, notElem, or, find, maximumBy, minimumBy, mapAccumL, mapAccumR, foldl')+import Data.Maybe as Exports+import Data.Monoid as Exports hiding (Last(..), First(..))+import Data.Ord as Exports+import Data.Proxy as Exports+import Data.Ratio as Exports+import Data.STRef as Exports+import Data.String as Exports+import Data.Traversable as Exports+import Data.Tuple as Exports+import Data.Unique as Exports+import Data.Version as Exports+import Data.Word as Exports+import Debug.Trace as Exports+import Foreign.ForeignPtr as Exports+import Foreign.Ptr as Exports+import Foreign.StablePtr as Exports+import Foreign.Storable as Exports+import GHC.Conc as Exports hiding (withMVar, threadWaitWriteSTM, threadWaitWrite, threadWaitReadSTM, threadWaitRead)+import GHC.Exts as Exports (lazy, inline, sortWith, groupWith)+import GHC.Generics as Exports (Generic)+import GHC.IO.Exception as Exports+import Numeric as Exports+import Prelude as Exports hiding (concat, foldr, mapM_, sequence_, foldl1, maximum, minimum, product, sum, all, and, any, concatMap, elem, foldl, foldr1, notElem, or, mapM, sequence, id, (.))+import System.Environment as Exports+import System.Exit as Exports+import System.IO as Exports+import System.IO.Error as Exports+import System.IO.Unsafe as Exports+import System.Mem as Exports+import System.Mem.StableName as Exports+import System.Timeout as Exports+import Text.ParserCombinators.ReadP as Exports (ReadP, ReadS, readP_to_S, readS_to_P)+import Text.ParserCombinators.ReadPrec as Exports (ReadPrec, readPrec_to_P, readP_to_Prec, readPrec_to_S, readS_to_Prec)+import Text.Printf as Exports (printf, hPrintf)+import Text.Read as Exports (Read(..), readMaybe, readEither)+import Unsafe.Coerce as Exports++-- transformers+-------------------------+import Control.Monad.IO.Class as Exports+import Control.Monad.Trans.Class as Exports+import Control.Monad.Trans.Cont as Exports hiding (shift, callCC)+import Control.Monad.Trans.Except as Exports (ExceptT(ExceptT), Except, except, runExcept, runExceptT, mapExcept, mapExceptT, withExcept, withExceptT)+import Control.Monad.Trans.Maybe as Exports+import Control.Monad.Trans.Reader as Exports (Reader, runReader, mapReader, withReader, ReaderT(ReaderT), runReaderT, mapReaderT, withReaderT)+import Control.Monad.Trans.State.Strict as Exports (State, runState, evalState, execState, mapState, withState, StateT(StateT), runStateT, evalStateT, execStateT, mapStateT, withStateT, state)+import Control.Monad.Trans.Writer.Strict as Exports (Writer, runWriter, execWriter, mapWriter, WriterT(..), execWriterT, mapWriterT)++-- deferred-folds+-------------------------+import DeferredFolds.Unfold as Exports (Unfold(..))++-- foldl+-------------------------+import Control.Foldl as Exports (Fold(..), FoldM(..))++-- hashable+-------------------------+import Data.Hashable as Exports (Hashable(..))++-- unordered-containers+-------------------------+import Data.HashMap.Strict as Exports (HashMap)++-- vector+-------------------------+import Data.Vector as Exports (Vector)++-- cereal+-------------------------+import Data.Serialize as Exports (Serialize)++-- bytestring+-------------------------+import Data.ByteString as Exports (ByteString)++-- profunctors+-------------------------+import Data.Profunctor as Exports hiding (WrappedArrow(..))++-- list-t+-------------------------+import ListT as Exports (ListT(..))++-- potoki-core+-------------------------+import Potoki.Core.Produce as Exports (Produce)+import Potoki.Core.Consume as Exports (Consume)+import Potoki.Core.Transform as Exports (Transform)+import Potoki.Core.Fetch as Exports (Fetch)
+ library/Indexation/Types.hs view
@@ -0,0 +1,14 @@+module Indexation.Types+where++import Indexation.Prelude+import qualified STMContainers.Map as A+++data Indexer entity = Indexer (TVar Int) (A.Map entity Int)++data IndexTable entity = IndexTable {-# UNPACK #-} !Int {-# UNPACK #-} !(HashMap entity Int)++newtype EntityTable entity = EntityTable (Vector entity)++newtype Index entity = Index Int
+ library/Indexation/Vector.hs view
@@ -0,0 +1,55 @@+module Indexation.Vector+where++import Indexation.Prelude+import Indexation.Types+import Data.Vector+import qualified Data.Vector.Mutable as A+import qualified Data.HashMap.Strict as B+import qualified ListT+import qualified STMContainers.Map as StmMap+++{-|+This function is not tested.+-}+{-# NOINLINE populate #-}+populate :: Monad effect => Int -> effect (Int, element) -> effect (Vector element)+populate size effect =+ do+ mv <- return (unsafeDupablePerformIO (A.unsafeNew size))+ let+ loop stepsRemaining =+ if stepsRemaining > 0+ then do+ (index, element) <- effect+ () <- return (unsafeDupablePerformIO (A.write mv index element))+ loop (pred stepsRemaining)+ else do+ !v <- return (unsafeDupablePerformIO (freeze mv))+ return v+ in loop size++{-|+This function is partial. It doesn't check the size or indices.+-}+{-# INLINE indexHashMapWithSize #-}+indexHashMapWithSize :: Int -> HashMap element Int -> Vector element+indexHashMapWithSize size hashMap =+ unsafePerformIO $ do+ mv <- A.unsafeNew size+ let+ step () element index = unsafeDupablePerformIO (A.write mv index element)+ !() = B.foldlWithKey' step () hashMap+ in freeze mv++{-# NOINLINE listT #-}+listT :: Monad m => Int -> ListT m (Int, element) -> m (Vector element)+listT size listT =+ let+ step mv (index, element) = return (unsafeDupablePerformIO (A.write mv index element $> mv))+ in do+ !mv <- return (unsafeDupablePerformIO (A.unsafeNew size))+ ListT.fold step mv listT+ !iv <- return (unsafeDupablePerformIO (unsafeFreeze mv))+ return iv