具有某种反射/内省的语言的巨大好处之一是可以从各种来源自动构造对象。
例如,在 Java 中,我可以使用相同的对象来持久化到数据库(使用 Hibernate)、序列化为 XML(使用 JAXB)以及序列化为 JSON(json-lib)。您可以在 Ruby 和 Python 中执行相同的操作,通常也遵循 Java 属性或注释的一些简单规则。
因此我不需要很多“域传输对象”。我可以专注于我正在工作的领域。
在像 Haskell 和 Ocaml 这样非常严格的 FP 中,这似乎是不可能的。
特别是哈斯克尔。我所看到的唯一的事情就是进行某种预处理或元编程(ocaml)。难道所有的转变都必须从下往上进行吗?
换句话说,你必须做很多无聊的工作才能将 haskell 中的数据类型转换为 JSON/XML/DB Row 对象,然后再转换回数据对象。
One of the huge benefits in languages that have some sort of reflection/introspecition is that objects can be automatically constructed from a variety of sources.
For example, in Java I can use the same objects for persisting to a db (with Hibernate), serializing to XML (with JAXB), and serializing to JSON (json-lib). You can do the same in Ruby and Python also usually following some simple rules for properties or annotations for Java.
Thus I don't need lots "Domain Transfer Objects". I can concentrate on the domain I am working in.
It seems in very strict FP like Haskell and Ocaml this is not possible.
Particularly Haskell. The only thing I have seen is doing some sort of preprocessing or meta-programming (ocaml). Is it just accepted that you have to do all the transformations from the bottom upwards?
In other words you have to do lots of boring work to turn a data type in haskell into a JSON/XML/DB Row object and back again into a data object.
发布评论
评论(5)
我无法与 OCaml 交谈,但我想说 Haskell 的主要困难是反序列化需要提前知道类型——没有通用的方法可以从格式中机械地反序列化,弄清楚结果值是什么,并从那里开始,这在具有不健全或动态类型系统的语言中是可能的。
抛开类型问题,Haskell 中有多种序列化数据的方法:
内置类型类
Read
/Show
(反)序列化代数数据类型和大多数内置类型都是字符串。行为良好的实例通常应该是read 。 show
相当于id
,并且show
的结果可以解析为构造序列化值的 Haskell 源代码。Hackage上可以找到各种序列化包;通常,这些要求要序列化的类型是某个类型类的实例,而包为大多数内置类型提供实例。有时,它们只需要类型具体化、反射元编程 Data 类的自动派生实例(迷人的完全限定名称为 Data.Data.Data),或者提供模板Haskell代码自动生成实例。
对于真正不寻常的序列化格式 - 或者创建您自己的包,如前面提到的那样 - 人们可以使用可用的最大锤子,有点像“老大哥”来
阅读
和< code>Show:解析和漂亮打印。有许多软件包可用于这两种格式,虽然一开始听起来可能令人生畏,但实际上 Haskell 中的解析和漂亮打印非常轻松。浏览一下 Hackage 就会发现,已经存在各种格式的序列化包,包括二进制数据、JSON、YAML 和 XML,尽管我没有使用过它们中的任何一个,所以我无法亲自证明它们的工作效果如何。下面是一个帮助您入门的非详尽列表:
ByteString
sByteString
s唯一的其他问题是,不可避免的是,并非所有类型都可序列化——如果不出意外的话,我怀疑您将会有一个很难序列化多态类型、存在类型和函数。
I can't speak to OCaml, but I'd say that the main difficulty in Haskell is that deserialization requires knowing the type in advance--there's no universal way to mechanically deserialize from a format, figure out what the resulting value is, and go from there, as is possible in languages with unsound or dynamic type systems.
Setting aside the type issue, there are various approaches to serializing data in Haskell:
The built-in type classes
Read
/Show
(de)serialize algebraic data types and most built-in types as strings. Well-behaved instances should generally be such thatread . show
is equivalent toid
, and that the result ofshow
can be parsed as Haskell source code constructing the serialized value.Various serialization packages can be found on Hackage; typically these require that the type to be serialized be an instance of some type class, with the package providing instances for most built-in types. Sometimes they merely require an automatically derivable instance of the type-reifying, reflective metaprogramming
Data
class (the charming fully qualified name for which isData.Data.Data
), or provide Template Haskell code to auto-generate instances.For truly unusual serialization formats--or to create your own package like the previously mentioned ones--one can reach for the biggest hammer available, sort of a "big brother" to
Read
andShow
: parsing and pretty-printing. Numerous packages are available for both, and while it may sound intimidating at first, parsing and pretty-printing are in fact amazingly painless in Haskell.A glance at Hackage indicates that serialization packages already exist for various formats, including binary data, JSON, YAML, and XML, though I've not used any of them so I can't personally attest to how well they work. Here's a non-exhaustive list to get you started:
ByteString
sByteString
sThe only other problem is that, inevitably, not all types will be serializable--if nothing else, I suspect you're going to have a hard time serializing polymorphic types, existential types, and functions.
就其价值而言,我认为 OCaml 中的预处理器解决方案(例如 sexplib、binprot 和 json-wheel 等)非常好(而且我认为人们使用 Template Haskell 做非常类似的事情)。它比反射更有效,并且还可以以自然的方式调整为个别类型。如果您不喜欢给定类型 foo 的自动生成的序列化器,您始终可以编写自己的序列化器,并且它非常适合包含 foo 作为组件的类型的自动生成的序列化器。
唯一的缺点是您需要学习 camlp4 才能为自己编写其中之一。但是,一旦您将构建系统设置为使用预处理器,使用它们就非常容易了。就像将
with sexp
添加到类型定义的末尾一样简单:现在您就拥有了序列化器。
For what it's worth, I think the pre-processor solution found in OCaml (as exemplified by sexplib, binprot and json-wheel among others) is pretty great (and I think people do very similar things with Template Haskell). It's far more efficient than reflection, and can also be tuned to individual types in a natural way. If you don't like the auto-generated serializer for a given type foo, you can always just write your own, and it fits beautifully into the auto-generated serializers for types that include foo as a component.
The only downside is that you need to learn camlp4 to write one of these for yourself. But using them is quite easy, once you get your build-system set up to use the preprocessor. It's as simple as adding
with sexp
to the end of a type definition:and now you have your serializer.
你想要
Haskell 中有多种方法可以序列化和反序列化数据类型。例如,您可以使用
以及其他常见共振峰 (协议缓冲区,thrift,xml)
每个包通常/通常带有宏或派生机制,以允许您派生 JSON。例如,对于 Data.Binary,请参阅之前的答案:Erlang's term_to_binary in Haskell?
一般的答案是:我们在 Haskell 中有许多很棒的序列化包,并且我们倾向于使用现有的类“派生”基础结构(使用泛型或模板 Haskell 宏来进行实际的派生)。
You wanted
There are many ways to serialize and unserialize data types in Haskell. You can use for example,
as well as other common formants (protocol buffers, thrift, xml)
Each package often/usually comes with a macro or deriving mechanism to allow you to e.g. derive JSON. For Data.Binary for example, see this previous answer: Erlang's term_to_binary in Haskell?
The general answer is: we have many great packages for serialization in Haskell, and we tend to use the existing class 'deriving' infrastructure (with either generics or template Haskell macros to do the actual deriving).
我的理解是,在 Haskell 中序列化和反序列化的最简单方法是从
Read
和Show
派生。这很简单,并不能满足您的要求。但是,还有 HXT 和 Text.JSON 这似乎提供了您所需要的。
My understanding is that the simplest way to serialize and deserialize in Haskell is to derive from
Read
andShow
. This is simple and isn't fullfilling your requirements.However there are HXT and Text.JSON which seem to provide what you need.
通常的方法是使用 Data.Binary。这提供了基本的序列化功能。数据类型的二进制实例易于编写,并且可以轻松地由较小的单元构建。
如果你想自动生成实例,那么你可以使用 Template Haskell。我不知道有任何软件包可以做到这一点,但如果已经存在,我不会感到惊讶。
The usual approach is to employ Data.Binary. This provides the basic serialisation capability. Binary instances for data types are easy to write and can easily be built out of smaller units.
If you want to generate the instances automatically then you can use Template Haskell. I don't know of any package to do this, but I wouldn't be surprised if one already exists.