操纵/扩展不受您控制的ADT的最佳方法是什么? (即来自依赖)
这里 是与我的问题相关的数据类型:
我想维护数据的结构,但添加额外的数据(即添加另一种类型),但结构本身不在我的控制之下。我是否必须将数据映射到我自己的此定义版本?
例如,对于结构中的所有段落,我想 Para
成为 Para [Inline] [String]
哪里 [String]
是段落中包含的单词列表(因为它是自己的数据结构)。
我通过端点将这些数据作为JSON提供,我认为我可以解决这个问题的方法是定义我自己的数据 ToJSON
实例,并执行此转换 Para
但是,我无法覆盖实例,因为它已经定义了!我愿意接受一个实际上没有触及的解决方案 Para
键入自己,我只需要一种方法来结合更多的数据 Para
不失任何结构的完整 Pandoc
文件。
但是我无法覆盖实例,因为它已经定义了!
您可以定义包装Pandoc的newtype,然后为其定义自定义ToJSON实例。 query
从 Text.Pandoc.Walk
可以轻松有效地从Para中提取字符串。
您可能考虑的另一件事是创建一个函数,它将Div中的每个Para包装在一个存储在其中一个属性中的字符串中。从您所说的内容来看,这是否适用于您的目的尚不清楚,但定义一个完成此转换的函数会很容易。
是的,我认为定义自己的 JSON
序列化器可能是最好的方法。你可以定义 JSON
序列化程序没有使用类型类机制,因为Aeson设计得很好(感谢@bos),只需从中定义一个函数 Block ->
Value
。不幸的是,您似乎必须手动遍历每个案例,至少是嵌套案例 Block
如 BlockQuote
, OrderedList
等等。对于其他人,你可以转发 ToJSON
:
serialize :: Block -> Value
serialize (BlockQuote bs) = object
[ "type" .= "blockquote" -- or whatever the encoding is
, "blocks" .= map serailize bs
]
... -- implement this for every constructor with recursive Blocks
serialize b = toJSON b
它并不好,因为你可能不得不直接重写已编写的内容。考虑到pandoc的设计,我没有看到解决方法(通常AST是通过一种注释来参数化的,例如: 哈斯克尔-SRC-EXTS,或使用一些开放式定点设计,这将允许更聪明的东西)。
一种相当粗略的方式是使用序列化 toJSON
,找到的部分 JSON
您想要注释的结构,反序列化该部分并计算注释,重新编译,然后添加您的计算注释。非常难看,但我认为你不必重新实现任何序列化器。如果pandoc有一个 批量 对于递归构造函数,或者非常复杂的序列化,我可能会考虑这一点,但就目前而言,我可能会咬紧牙关并重新实现递归的情况。