수백만 개의 항목이 포함 된 큰 해시 맵이 있는데이를 디스크에 유지하므로 디스크에서 다시 읽을 때 키 - 값 쌍을지도에 다시 삽입하는 데 오버 헤드가 발생하지 않습니다. 다시.해시 맵을 직렬화/비 직렬화하는 방법은 무엇입니까?
시리얼 라이브러리를 사용하려고하는데, HashMap 데이터 유형이 일반을 파생해야합니다. 이것을 할 수있는 방법이 있습니까?
수백만 개의 항목이 포함 된 큰 해시 맵이 있는데이를 디스크에 유지하므로 디스크에서 다시 읽을 때 키 - 값 쌍을지도에 다시 삽입하는 데 오버 헤드가 발생하지 않습니다. 다시.해시 맵을 직렬화/비 직렬화하는 방법은 무엇입니까?
시리얼 라이브러리를 사용하려고하는데, HashMap 데이터 유형이 일반을 파생해야합니다. 이것을 할 수있는 방법이 있습니까?
현재 HashMap 라이브러리 자체를 수정하지 않고도 HashMap을 직렬화 할 수있는 방법은 없습니다.
@ mergeconflict의 대답에 설명 된 독립 실행 형 파생을 사용하여 Data.HashMap을 Generic (인스턴스와 함께 사용)의 인스턴스로 만들 수 없습니다. Data.HashMap은 모든 생성자를 내보내지 않기 때문에 필수 항목입니다. GHC).
따라서 HashMap을 직렬화하는 유일한 해결책은 toList/fromList 인터페이스를 사용하는 것입니다.
stand-alone deriving을 사용하여 HashMap
에 대해 Generic
인스턴스를 생성 할 수 있습니다. 당신은 아마도 orphan instances에 대한 경고를 얻을 것이다. 그러나 당신은 또한 상관하지 않을 것이다. :) 어쨌든, 나는 이것을 시도하지 않았지만, 아마도 그럴만한 가치가있다 ...
나는 이것이 좋은 대답이라고 생각한다. 또 하나의 요점은 아마도 고아 인스턴스를 피하는 방법에 대한 트릭이다. 간단히 HashMap을 래핑하는 newtype을 정의하고이 유형에 대한 인스턴스를 정의한다. HashMap을 직렬화해야 할 때 유형에 랩핑하고 직렬화하면됩니다. – Tener
@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 Bummer :( – mergeconflict
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만을위한 일이 될 것입니다.
CerealPlus 패키지는 엄격한 HashMaps에 대해 Serialize를 정의합니다. 이진 사용할 수있는 경우
는 정렬되지 않은-컨테이너 인스턴스를 제공 이진 고아있다. 일부 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
Generic을 파생하는 문제는 무엇입니까? 데이터 유형이 Hackage에 도서관에 제출하는 것보다 (다른 경우이 작업을 수행 할 수있는 방법 Generic' 유도 = 뭔가 '데이터 뭔가 지능 지능 : – Cubic
는 일반을 유도하기 위해, 사용자 정의 유형, 우리는 같은 것을 작성해야 라이브러리의 관리자에 대한 패치)? – donatello
음 ...글쎄, 나는 개인적으로 이처럼 Serializing HashMaps가 작동하지 않는다고 의심하고, 당신이 원하는 직렬화를 지원하는 다른 구현체를 사용해야 만한다.하지만 다른 사람들이 말하는 것을 볼 수있다. – Cubic