2014-09-25 18 views
5

Uygulamamda bir veritabanından (şu anda yerel bir düz dosya ...) nesneleri depolayıp yüklüyorum. Bu nesnelerin tümü, Event a tipindeki bir aileden gelir ve hepsi de ByteString'dan/'dan seri hale getirilebilir. gerekli türleri ile birlikteHaskell'de genel deserialisation nasıl kullanılır?

class BusinessModel a where 
    data Event a :: * 
    apply :: a -> Event a -> a 

Ve uygulanmasının örneği,: Burada

data User = User { userId :: UserId, userName :: Text } deriving (Eq, Show, Read, Generic) 

instance ToJSON User 
instance FromJSON User 

type UsersView = M.Map UserId User 

instance BusinessModel UsersView where 

    data Event UsersView = NoEvent    -- ^A no-op event 
         | UserRegistered User 
         deriving (Eq, Show, Read, Generic) 

    apply v (UserRegistered u) = insert (userId u) u v 
    apply v _     = v 

ama değişebilir tip ailede a ... İşte

taban sınıfı beyanıdır olayım için geçerli arabirim:

class (MonadIO store) => EventStore store where 
    -- store a single event 
    store :: Serializable s => s -> store() 
    -- load all events from the store 
    load :: Serializable s => store [s] 

Daha sonra abl olmamız gerekiyor

instance ToJSON (Event UsersView) 
instance FromJSON (Event UsersView) 

instance Serializable (Event UsersView) where 
    read = fromJust . decode 
    write = encode 

ben içeren bir yapı içinde doğru a her Event a uygulamak, sonra bütün a için, kayıtlı tüm Event a nesneleri deserialise edebilmek istiyorum: E biz sadece Json gösterimi kullanabilir burada (olayları tefrika farklı olaylar "hedef". load'u saf bir şekilde kullanmaya çalıştığımda, birden çok örneği Serializable olması ve doğru olanı seçememe zorluğuyla karşılaşıyorum.

Başımın en üstünde, basit bir çözüm düşünebiliyordum: Her olayı uygun a ile okunacak şekilde etiketleyin, ama bu çok zarif görünmüyor mu?

Bu tür bir problem için en iyi yaklaşım nedir?

+1

Her olayı düzgün bir şekilde a ile etiketleyin. –

+0

Teşekkürler. Kod/paket üzerinde benzer şeyler yapan işaretçiler var mı? Sanırım bunu uygulayan ilk kişi ben değilim. – insitu

+0

Aeson paketi benzer bir şey yapar, bu da bakmak için tek bir yer olabilir. Yine de birilerinin daha iyi bir cevap vereceğini umuyordum. –

cevap

2

Gerçekten ne yapmaya çalıştığınız için Haskell'de uygun, otomatik bir yöntem yoktur. Rasgele değerleri deserialize etmek ve bunları arayüzler aracılığıyla çalışma zamanı polimorfik yöntemlerle kullanmak, nesne yönelimli bir modelden daha fazladır.

Kendiniz söylediğiniz gibi, serileştirme ve serileştirme için, tür bilgilerini depolamak ve geri yüklemek için olayları bir şekilde etiketlemeniz gerekir. Örneğin.

data TaggedEvent 
    = EventUsersView (Event UsersView) 
    | EventSomeOtherView (Event SomeOtherView) 
    ... 

acid-state olaylar için, örneğin yapıldığı gibi TaggedEvent tipi otomatik olarak şablon Haskell kullanılarak üretilebilir olabilir, bazı el standart metni kaldırın.

+0

Cevabınız için teşekkürler. Ne yapmaya çalıştığım için uygun bir fonksiyonel kalıp ne olurdu? Uygulama durumunun geçici, değişmez ve olaylarla değiştirildiği, olayın sistemdeki tek kalıcı parçası olduğu bazı olay kaynaklı uygulamaları uyguluyorum. AFAICT, bu tipik olarak işlevseldir. – insitu

+0

FWIW, bu soruya işaret edilen etiket tabanlı yaklaşımı uyguladık: http: // stackoverflow.com/questions/26117165/how-to-handle-or-avoid-blockedindefinitelyonstm-exception Görüntülerin gerçekten bu etiket hakkında bilgi sahibi olmadığından emin olmak için yazarak ve uygun tip sınıflarıyla biraz uğraşmak zorunda kaldım, ama iyi çalışıyor. – insitu

İlgili konular