具有某种反射/内省规范的语言的巨大好处之一是可以从各种来源自动构建对象。
例如,在Java中,我可以使用相同的对象来持久化到db(使用Hibernate),序列化为XML(使用JAXB),以及序列化为JSON(json-lib)。您可以在Ruby和Python中执行相同的操作,通常也遵循一些简单的Java属性或注释规则。
因此我不需要很多“域转移对象”。我可以专注于我正在工作的领域。
似乎在非常严格的FP中,如Haskell和Ocaml,这是不可能的。 特别是Haskell。我唯一看到的是进行某种预处理或元编程(ocaml)。刚刚接受你必须从下到上进行所有转换吗?
换句话说,你必须做很多无聊的工作才能将haskell中的数据类型转换为JSON / XML / DB Row对象,然后再转换回数据对象。
答案 0 :(得分:28)
我不能和OCaml说话,但我会说Haskell的主要困难是反序列化需要事先知道类型 - 没有通用的方法从格式中进行机械反序列化,找出结果值是什么,并从那里开始,就像在有不健全或动态类型系统的语言中一样。
抛开类型问题,有各种方法在Haskell中序列化数据:
内置类型类Read
/ Show
(de)将代数数据类型和大多数内置类型序列化为字符串。行为良好的实例通常应该read . show
等同于id
,并且show
的结果可以解析为构造序列化值的Haskell源代码。
可以在Hackage上找到各种序列化包;通常这些要求要序列化的类型是某个类型类的实例,该包提供大多数内置类型的实例。有时它们只需要一个自动派生的类型实现,反射式元编程Data
类(其中有Data.Data.Data
的完全限定名称)的实例,或者提供模板Haskell代码来自动生成实例。 / p>
对于真正不寻常的序列化格式 - 或者像前面提到的那样创建自己的包 - 人们可以找到最大的锤子,有点像Read
和{{大哥哥' {1}}:解析和漂亮打印。两者都可以使用许多软件包,虽然它起初可能听起来令人生畏,但在Haskell中,解析和漂亮打印实际上是非常轻松的。
对Hackage的一瞥表明已经存在各种格式的序列化包,包括二进制数据,JSON,YAML和XML,虽然我没有使用它们,所以我无法亲自证明它们的工作情况。这是一个非详尽的列表,可以帮助您入门:
Show
s ByteString
s 唯一的另一个问题是,不可避免地,并非所有类型都可以序列化 - 如果没有别的,我怀疑你将很难序列化多态类型,存在类型和函数。
答案 1 :(得分:5)
对于它的价值,我认为在OCaml中找到的预处理器解决方案(例如sexplib,binprot和json-wheel等)非常棒(我认为人们使用Template Haskell做了非常相似的事情)。它比反射效率高得多,也可以自然地调整到各种类型。如果您不喜欢给定类型foo的自动生成的序列化程序,您可以随时编写自己的序列化程序,并且它非常适合包含foo作为组件的类型的自动生成的序列化程序。
唯一的缺点是你需要学习camlp4为自己编写其中一个。但是,一旦将构建系统设置为使用预处理器,使用它们就非常容易。就像在类型定义的末尾添加with sexp
一样简单:
type t = { foo: int; bar: float }
with sexp
现在你有了序列化器。
答案 2 :(得分:5)
你想要
做很多无聊的工作,将haskell中的数据类型转换为JSON / XML / DB Row对象,然后再转换回数据对象。
在Haskell中有许多方法可以序列化和反序列化数据类型。您可以使用例如
以及其他常见共振峰(protocol buffers,thrift,xml)
每个包经常/通常附带一个宏或派生机制,以允许您例如派生JSON。例如,对于Data.Binary,请参阅前面的答案:Erlang's term_to_binary in Haskell?
一般的答案是:我们在Haskell中有很多很好的序列化包,我们倾向于使用现有的类'derived''基础结构(使用泛型或模板Haskell宏来进行实际派生)。
答案 3 :(得分:4)
答案 4 :(得分:3)
通常的做法是使用Data.Binary。这提供了基本的序列化功能。数据类型的二进制实例易于编写,可以很容易地用较小的单元构建。
如果要自动生成实例,则可以使用Template Haskell。我不知道有任何方法可以做到这一点,但如果已经存在,我不会感到惊讶。