如何在haskell中处理泛型反序列化?

如何在haskell中处理泛型反序列化?,haskell,deserialization,Haskell,Deserialization,在我的应用程序中,我存储并加载数据库中的对象(当前是本地平面文件…)。这些对象都来自类型族事件a,并且都可以通过TestRing向/从序列化。但是类型族中的a可能会有所不同 下面是基类声明: class BusinessModel a where data Event a :: * apply :: a -> Event a -> a 和一个示例实现,以及所需的类型: data User = User { userId :: UserId, userName :: Te

在我的应用程序中,我存储并加载数据库中的对象(当前是本地平面文件…)。这些对象都来自类型族
事件a
,并且都可以通过TestRing向/从
序列化。但是类型族中的
a
可能会有所不同

下面是基类声明:

class BusinessModel a where
  data Event a   :: *
  apply :: a -> Event a -> a
和一个示例实现,以及所需的类型:

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
以下是我的事件存储的当前接口:

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]
然后我们需要能够序列化事件(这里我们只使用Json表示:

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

instance Serializable (Event UsersView) where
  read  = fromJust . decode
  write = encode
我希望能够为所有
a
反序列化所有存储的
Event a
对象,然后将每个
Event a
应用到包含不同事件“target”的结构中正确的
a
。当我尝试天真地使用
load
时,我遇到了麻烦,因为有多个
Serializable
实例,而无法选择正确的实例

在我脑海中,我想到了一个简单的解决方案:用它所涉及的适当的
a
标记每个要阅读的事件,但这似乎不是很优雅


解决这类问题的最佳方法是什么?

Haskell中确实没有方便、自动的方法来完成您正在尝试的工作。反序列化任意值并通过接口以运行时多态方式使用它们更像是一种面向对象的模式

正如您自己所说,对于序列化和反序列化,您需要以某种方式标记事件以存储和恢复类型信息

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

要删除一些手动样板文件,可以使用模板Haskell自动生成
TaggedEvent
类型,例如中的事件。

用适当的
a
标记每个事件。谢谢。你有代码/包上的指针做类似的事情吗?我想我不是第一个实现这一点的人。aeson package做了一些类似的事情,这可能是一个值得一看的地方。我仍然希望有人能给出一个更好的答案。你能添加一个最小的可编译示例吗?或者至少为你的类型族和几个实例添加定义吗?谢谢@shang。希望添加了代码的相关部分。谢谢你的回答。有什么好玩的我正在实现一些事件源应用程序,其中应用程序的状态是瞬时的、不可变的,并且通过事件进行修改,后者是系统唯一的持久部分。AFAICT,这通常是功能性的。FWIW,我实现了这个问题中暗示的基于标记的方法:I必须稍微修改一下类型和适当的类型类,以确保视图实际上不知道这个标记,但它可以正常工作。