diff --git a/edges.cabal b/edges.cabal
--- a/edges.cabal
+++ b/edges.cabal
@@ -1,45 +1,22 @@
-name:
-  edges
-version:
-  0.8.1
-category:
-  Graphs
-synopsis:
-  Tools for efficient immutable graphs
-description:
-  A set of tools for constructing immutable graphs which are both memory and performance-efficient.
-homepage:
-  https://github.com/metrix-ai/edges
-bug-reports:
-  https://github.com/metrix-ai/edges/issues
-author:
-  Nikita Volkov <nikita.y.volkov@mail.ru>
-maintainer:
-  Metrix Tech Team <tech@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/metrix-ai/edges.git
+name: edges
+version: 0.9
+category: Graphs
+synopsis: Tools for efficient immutable graphs
+description: A set of tools for constructing immutable graphs which are both memory and performance-efficient.
+homepage: https://github.com/metrix-ai/edges
+bug-reports: https://github.com/metrix-ai/edges/issues
+author: Nikita Volkov <nikita.y.volkov@mail.ru>
+maintainer: Metrix.AI Tech Team <tech@metrix.ai>
+copyright: (c) 2018, Metrix.AI
+license: MIT
+license-file: LICENSE
+build-type: Simple
+cabal-version: >=1.10
 
 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, OverloadedLists
-  default-language:
-    Haskell2010
+  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, OverloadedLists, PatternGuards, PatternSynonyms, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeApplications, TypeFamilies, TypeOperators, UnboxedTuples
+  default-language: Haskell2010
   exposed-modules:
     Edges.Data
     Edges.Folds
@@ -50,6 +27,7 @@
     Edges.Gens
   other-modules:
     Edges.Functions
+    Edges.Functions.Folds
     Edges.Instances
     Edges.Instances.Cereal
     Edges.Cereal.Get
@@ -62,6 +40,7 @@
     contravariant >=1.4 && <2,
     deferred-folds >=0.6 && <0.7,
     foldl >=1.4.2 && <2,
+    hashable >=1.2 && <2,
     monad-par >=0.3.4.8 && <0.4,
     pointed >=5 && <6,
     potoki >=2.0.2 && <2.1,
@@ -72,19 +51,15 @@
     QuickCheck >=2.8.1 && <3,
     semigroupoids >=5.2 && <6,
     text >=1 && <2,
+    unordered-containers >=0.2 && <0.3,
     vector >=0.12 && <0.13
 
 test-suite test
-  type:
-    exitcode-stdio-1.0
-  hs-source-dirs:
-    test
-  main-is:
-    Main.hs
-  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, OverloadedLists
-  default-language:
-    Haskell2010
+  type: exitcode-stdio-1.0
+  hs-source-dirs: test
+  main-is: Main.hs
+  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, OverloadedLists, PatternGuards, PatternSynonyms, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeApplications, TypeFamilies, TypeOperators, UnboxedTuples
+  default-language: Haskell2010
   build-depends:
     cereal,
     edges,
diff --git a/library/Edges/Cereal/Get.hs b/library/Edges/Cereal/Get.hs
--- a/library/Edges/Cereal/Get.hs
+++ b/library/Edges/Cereal/Get.hs
@@ -3,23 +3,20 @@
 
 import Edges.Prelude
 import Edges.Types
-import Data.Serialize.Get
+import Data.Serialize
 import qualified PrimitiveExtras.PrimArray as PrimArray
 import qualified PrimitiveExtras.PrimMultiArray as PrimMultiArray
 
 
-int :: Get Int
-int = fromIntegral <$> getInt64le
-
 nodeCounts :: Get (NodeCounts entity)
 nodeCounts =
-  NodeCounts <$> PrimArray.cerealGet int getWord32le
+  NodeCounts <$> PrimArray.cerealGetAsInMemory get
 
 edges :: Get (Edges a b)
 edges = do
-  targetSpace <- int
-  pma <- PrimMultiArray.cerealGet int getWord32le
+  targetSpace <- get
+  pma <- PrimMultiArray.cerealGetAsInMemory get
   return (Edges targetSpace pma)
 
 node :: Get (Node a)
-node = Node <$> int
+node = Node <$> get
diff --git a/library/Edges/Cereal/Put.hs b/library/Edges/Cereal/Put.hs
--- a/library/Edges/Cereal/Put.hs
+++ b/library/Edges/Cereal/Put.hs
@@ -3,22 +3,19 @@
 
 import Edges.Prelude
 import Edges.Types
-import Data.Serialize.Put
+import Data.Serialize
 import qualified PrimitiveExtras.PrimArray as PrimArray
 import qualified PrimitiveExtras.PrimMultiArray as PrimMultiArray
 
 
-int :: Putter Int
-int = putInt64le . fromIntegral
-
 nodeCounts :: Putter (NodeCounts entity)
 nodeCounts (NodeCounts pa) =
-  PrimArray.cerealPut int putWord32le pa
+  PrimArray.cerealPutAsInMemory put pa
 
 edges :: Putter (Edges a b)
 edges (Edges targetSpaceValue mpaValue) = targetSpace <> mpa where
-  targetSpace = int targetSpaceValue
-  mpa = PrimMultiArray.cerealPut int putWord32le mpaValue
+  targetSpace = put targetSpaceValue
+  mpa = PrimMultiArray.cerealPutAsInMemory put mpaValue
 
 node :: Putter (Node a)
-node (Node x) = int x
+node (Node x) = put x
diff --git a/library/Edges/Functions.hs b/library/Edges/Functions.hs
--- a/library/Edges/Functions.hs
+++ b/library/Edges/Functions.hs
@@ -4,8 +4,10 @@
 import Edges.Prelude
 import Edges.Types
 import qualified Data.Vector.Unboxed as UnboxedVector
+import qualified DeferredFolds.Unfold as Unfold
 import qualified DeferredFolds.UnfoldM as UnfoldM
 import qualified Control.Foldl as Foldl
+import qualified Edges.Functions.Folds as Foldl
 import qualified Control.Monad.Par as Par
 import qualified PrimitiveExtras.PrimMultiArray as PrimMultiArray
 import qualified PrimitiveExtras.PrimArray as PrimArray
@@ -65,3 +67,7 @@
 
 nodeCountsUnboxedVector :: NodeCounts entity -> UnboxedVector.Vector Word32
 nodeCountsUnboxedVector (NodeCounts pa) = PrimArray.toUnboxedVector pa
+
+unindexNodeCounts :: (Eq entity, Hashable entity) => (Int -> Maybe entity) -> NodeCounts entity -> HashMap entity Int
+unindexNodeCounts lookup (NodeCounts pa) =
+  Unfold.fold (Foldl.hashMapByKeyLookup lookup) (fmap fromIntegral (Unfold.primArray pa))
diff --git a/library/Edges/Functions/Folds.hs b/library/Edges/Functions/Folds.hs
new file mode 100644
--- /dev/null
+++ b/library/Edges/Functions/Folds.hs
@@ -0,0 +1,17 @@
+module Edges.Functions.Folds
+where
+
+import Edges.Prelude
+import Edges.Types
+import Control.Foldl
+import qualified Data.HashMap.Strict as HashMap
+
+
+hashMapByKeyLookup :: (Eq b, Hashable b) => (a -> Maybe b) -> Fold a (HashMap b a)
+hashMapByKeyLookup lookup = Fold (flip updateMap) init extract where
+  updateMap a = case lookup a of
+    Just b -> HashMap.insert b a
+    Nothing -> id
+  init = HashMap.empty
+  extract = id
+
diff --git a/library/Edges/Prelude.hs b/library/Edges/Prelude.hs
--- a/library/Edges/Prelude.hs
+++ b/library/Edges/Prelude.hs
@@ -108,6 +108,10 @@
 -------------------------
 import Control.Foldl as Exports (Fold(..), FoldM(..))
 
+-- hashable
+-------------------------
+import Data.Hashable as Exports (Hashable)
+
 -- primitive
 -------------------------
 import Data.Primitive as Exports
@@ -117,6 +121,10 @@
 -------------------------
 import PrimitiveExtras.PrimMultiArray as Exports (PrimMultiArray)
 import PrimitiveExtras.TVarArray as Exports (TVarArray)
+
+-- unordered-containers
+-------------------------
+import Data.HashMap.Strict as Exports (HashMap)
 
 -- vector
 -------------------------
