Haskell 如何序列化/反序列化哈希映射?

Haskell 如何序列化/反序列化哈希映射?,haskell,serialization,Haskell,Serialization,我有一个包含数百万条目的大型hashmap,我想将它持久化到磁盘,这样当它再次从磁盘读取时,我就不会有再次将键值对插入映射的开销 我正试图使用谷物库来实现这一点,但数据类型似乎需要派生泛型。有什么方法可以做到这一点吗?您可以使用它为HashMap生成自己的泛型实例。您可能会收到关于的警告,但您也可能不在乎:)无论如何,我没有尝试过这个,但它可能值得一试…我不确定使用泛型是否是实现高性能的最佳途径。我的最佳选择实际上是为Serializable编写您自己的实例,如下所示: instance (Se

我有一个包含数百万条目的大型hashmap,我想将它持久化到磁盘,这样当它再次从磁盘读取时,我就不会有再次将键值对插入映射的开销


我正试图使用谷物库来实现这一点,但数据类型似乎需要派生泛型。有什么方法可以做到这一点吗?

您可以使用它为
HashMap
生成自己的
泛型
实例。您可能会收到关于的警告,但您也可能不在乎:)无论如何,我没有尝试过这个,但它可能值得一试…

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

instance (Serializable a) => Serializable (HashMap a) where
  ...
要避免创建孤立实例,可以使用newtype技巧:

newtype SerializableHashMap a = SerializableHashMap { toHashMap :: HashMap a }
instance (Serializable a) => SerializableHashMap a where
  ...
问题是如何定义

在您实际尝试、实施和测试可能的解决方案之前,没有明确的答案

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


另一种方法(类似于使用泛型)是基于内部HashMap结构编写直接序列化。考虑到您没有真正导出仅用于泛型的内部构件。

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

无法使用@mergeconflict的答案所述的独立派生将Data.HashMap作为泛型(用于谷物)的实例,因为Data.HashMap不会导出其所有构造函数(这是GHC的要求)


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

CeralPlus包为严格的HashMap提供了序列化的定义


如果您可以使用二进制,那么就有二进制孤立项,它为无序容器提供实例。由于某些阴谋集团的冲突,我无法安装二进制孤儿,但只是抢走了我需要的部件,例如:

{-# 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

派生泛型有什么问题?要派生泛型,对于自定义类型,我们需要编写如下内容:
data something=somethint Int派生泛型
如果数据类型在黑客攻击时位于库中(而不是向库的维护者提交补丁),那么如何才能做到这一点。。。好吧,我个人怀疑像这样序列化HashMaps是行不通的,最终你将不得不使用另一个支持你想要的序列化类型的实现,但是让我们看看其他人怎么说。在你放弃toList/fromList方法之前,你估计需要多长时间?25秒在我4岁的笔记本电脑上插入1000万(整数,字符串)键/值对。@ja。它速度很快,但直观地看,按原样序列化结构很容易(而且效率更高)。fromList/toList似乎是唯一的方法,因为
通用的
方法不起作用(参见我对mergeconflict答案的评论)。我认为这是一个很好的答案。还有一点可能是关于如何避免孤立实例的技巧:只需定义一个包装HashMap的新类型并定义该类型的实例。当您需要序列化HashMap时,只需将其包装在您的类型中并序列化。@mergeconflict,@Tener I添加了一行:
派生实例(Generic k,Generic v)=>Generic(H.HashMap k v)
,但GHC抱怨HashMap的所有数据构造函数都不在范围内(即)。看来这种方法终究行不通。