Nella mia applicazione memorizzo e carico oggetti da un database (attualmente un file flat locale ...). Questi oggetti appartengono tutti a una famiglia di tipi Event a
e sono anche tutti serializzabili a/da ByteString
. Ma il a
nella famiglia tipo può variare ...Come gestire la deserializzazione generica in haskell?
Ecco la dichiarazione della classe di base:
class BusinessModel a where
data Event a :: *
apply :: a -> Event a -> a
E un esempio di implementazione, insieme ai tipi necessari:
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
Ecco il interfaccia corrente al mio negozio di eventi:
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]
Quindi dobbiamo essere abl e per puntate eventi (qui usiamo semplicemente la rappresentazione JSON:
instance ToJSON (Event UsersView)
instance FromJSON (Event UsersView)
instance Serializable (Event UsersView) where
read = fromJust . decode
write = encode
Vorrei essere in grado di deserialise tutte le stored Event a
oggetti, per tutti a
, quindi applicare ogni Event a
alla corretta a
all'interno di una struttura che contiene eventi diversi "target". Quando provo a usare in modo ingenuo lo load
, mi imbatto nel problema di avere più istanze di Serializable
e di non essere in grado di scegliere quello giusto.
Fuori dalla cima della mia testa, ho potuto pensare ad una soluzione semplice: tagga ogni evento da leggere con l'appropriato a
a cui appartiene, ma questo non sembra molto elegante?
Qual è l'approccio migliore a questo tipo di problema?
Contrassegna ogni evento con l'appropriato 'a'. –
Grazie. Avete indicazioni su codice/pacchetto che fanno cose simili? Immagino di non essere il primo a implementarlo. – insitu
Il pacchetto aeson fa qualcosa di simile-ish, che potrebbe essere un posto dove guardare. Sto ancora sperando che qualcuno possa dare una risposta migliore. –