如何序列化/反序列化hashmap?

时间:2012-06-23 12:35:03

标签: haskell serialization

我有一个包含数百万个条目的大型hashmap,我想将它保存到磁盘,这样当它再次从磁盘读取时,我没有将键值对重新插入到磁盘中的开销。再次映射。

我正在尝试使用谷物库来执行此操作,但似乎HashMap数据类型需要派生Generic。有没有办法做到这一点?

5 个答案:

答案 0 :(得分:5)

您可以使用stand-alone derivingGeneric生成自己的HashMap个实例。您可能会收到有关orphan instances的警告,但您也可能不在乎:)无论如何,我没有尝试过这个,但它可能值得一试......

答案 1 :(得分:1)

我不确定使用Generics是否是实现高性能的最佳选择。我最好的选择实际上是为Serializable编写自己的实例,如下所示:

instance (Serializable a) => Serializable (HashMap a) where
  ...

为避免创建孤立实例,您可以使用newtype trick:

newtype SerializableHashMap a = SerializableHashMap { toHashMap :: HashMap a }
instance (Serializable a) => SerializableHashMap a where
  ...

问题是如何定义...

在您真正尝试实施和对可能的解决方案进行基准测试之前,没有明确的答案。

一种可能的解决方案是使用toList / fromList函数并存储/读取HashMap的大小。

另一个(类似于使用Generics)将基于内部HashMap结构编写直接序列化。鉴于您实际上没有导出的内部结构,这只是Generics的工作。

答案 2 :(得分:0)

目前,如果不修改HashMap库本身,就无法使HashMap可序列化。

使用@ mergeconflict的答案所描述的独立派生,不可能使Data.HashMap成为Generic的实例(用于谷物),因为Data.HashMap不会导出其所有构造函数(这是一个要求GHC)。

因此,序列化HashMap的唯一解决方案似乎是使用toList / fromList接口。

答案 3 :(得分:0)

如果你可以使用二进制文件,那就是二元孤儿,它为无序容器提供实例。由于一些影响冲突,我无法安装二元孤儿,但只是抓住了我需要的部分,例如:

{-# LANGUAGE CPP           #-}
{-# LANGUAGE DeriveGeneric #-}

module Bin where

import           Data.Binary
import           Data.ByteString.Lazy.Internal
import           Data.Hashable                 (Hashable)
import qualified Data.HashMap.Strict           as M
import qualified Data.Text                     as T

#if !(MIN_VERSION_text(1,2,1))
import           Data.Text.Binary              ()
#endif

instance  (Hashable k, Eq k, Binary k, Binary v) => Binary (M.HashMap k v) where
  get = fmap M.fromList get
  put = put . M.toList

-- Note: plain `encode M.fromList []` without type annotations won't work
encodeModel :: M.HashMap T.Text Int -> ByteString
encodeModel m =
  encode m

答案 4 :(得分:-1)

CerealPlus包提供严格HashMaps的Serialize定义。

http://hackage.haskell.org/package/cereal-plus