2012-06-23 6 views
10

수백만 개의 항목이 포함 된 큰 해시 맵이 있는데이를 디스크에 유지하므로 디스크에서 다시 읽을 때 키 - 값 쌍을지도에 다시 삽입하는 데 오버 헤드가 발생하지 않습니다. 다시.해시 맵을 직렬화/비 직렬화하는 방법은 무엇입니까?

시리얼 라이브러리를 사용하려고하는데, HashMap 데이터 유형이 일반을 파생해야합니다. 이것을 할 수있는 방법이 있습니까?

+0

Generic을 파생하는 문제는 무엇입니까? 데이터 유형이 Hackage에 도서관에 제출하는 것보다 (다른 경우이 작업을 수행 할 수있는 방법 Generic' 유도 = 뭔가 '데이터 뭔가 지능 지능 : – Cubic

+1

는 일반을 유도하기 위해, 사용자 정의 유형, 우리는 같은 것을 작성해야 라이브러리의 관리자에 대한 패치)? – donatello

+0

음 ...글쎄, 나는 개인적으로 이처럼 Serializing HashMaps가 작동하지 않는다고 의심하고, 당신이 원하는 직렬화를 지원하는 다른 구현체를 사용해야 만한다.하지만 다른 사람들이 말하는 것을 볼 수있다. – Cubic

답변

0

현재 HashMap 라이브러리 자체를 수정하지 않고도 HashMap을 직렬화 할 수있는 방법은 없습니다.

@ mergeconflict의 대답에 설명 된 독립 실행 형 파생을 사용하여 Data.HashMap을 Generic (인스턴스와 함께 사용)의 인스턴스로 만들 수 없습니다. Data.HashMap은 모든 생성자를 내보내지 않기 때문에 필수 항목입니다. GHC).

따라서 HashMap을 직렬화하는 유일한 해결책은 toList/fromList 인터페이스를 사용하는 것입니다.

5

stand-alone deriving을 사용하여 HashMap에 대해 Generic 인스턴스를 생성 할 수 있습니다. 당신은 아마도 orphan instances에 대한 경고를 얻을 것이다. 그러나 당신은 또한 상관하지 않을 것이다. :) 어쨌든, 나는 이것을 시도하지 않았지만, 아마도 그럴만한 가치가있다 ...

+2

나는 이것이 좋은 대답이라고 생각한다. 또 하나의 요점은 아마도 고아 인스턴스를 피하는 방법에 대한 트릭이다. 간단히 HashMap을 래핑하는 newtype을 정의하고이 유형에 대한 인스턴스를 정의한다. HashMap을 직렬화해야 할 때 유형에 랩핑하고 직렬화하면됩니다. – Tener

+0

@mergeconflict, @Tener '파생 인스턴스 (일반 k, 일반 v) => 일반 (H.HashMap kv)' 그러나 GHC는 HashMap의 모든 데이터 생성자가 범위에 있지 않다고 불평합니다 [모두 내보낼 수는 없습니다.] (http://hackage.haskell.org/packages/archive/unordered-containers/0.2.1.0/doc/html/src/Data-HashMap-Base.html#HashMap)). 이 접근 방식이 결국 작동하지 않는 것처럼 보입니다. donatello

+0

@donatello Bummer :( – mergeconflict

1

Generics를 사용하고 있는지 확실하지 않다. 고성능 달성에있어서 최고의 기회. 나의 가장 좋은 방법은 실제로이 같은 직렬화에 대한 자신의 인스턴스를 작성하는 것입니다 :

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

이 문제는 어떻게 ...을 정의하는 것입니다 :

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

당신이 newtype은 트릭을 사용하여 생성 고아 인스턴스를 방지하려면?

가능한 해결책을 실제로 구현하고 벤치 마크하기 전에 확실한 답이 없습니다.

가능한 해결책 중 하나는 toList/fromList 기능을 사용하고 HashMap의 크기를 저장/읽는 것입니다.

기타 (Generics를 사용하는 것과 비슷 함)는 내부 HashMap 구조를 기반으로 직접 직렬화를 작성하는 것입니다. 당신이 실제로 내실을 수출하지 않는다는 사실을 감안할 때 Generics만을위한 일이 될 것입니다.

0

는 정렬되지 않은-컨테이너 인스턴스를 제공 이진 고아있다. 일부 cabal 충돌로 인해 바이너리 - 고아를 설치할 수 없지만 필요한 부분 만 빼앗 겼습니다 (예 :

{-# 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 
관련 문제