操作/扩展不在您控制范围内的ADT的最佳方法是什么?(来自依赖关系)
以下是与我的问题相关的数据类型:
我想维护数据的结构,但添加额外的数据(即添加另一种类型),但结构本身不在我的控制之下。我是否必须将数据映射到我自己的定义版本?
例如,对于结构中的所有段落,我希望Para
变成Para [Inline] [String]
,其中[String]
是包含在段落中的单词列表(作为它自己的数据结构)。
我通过一个端点将这些数据作为JSON提供,我想我可以绕过这一点的一种方法是定义我自己的ToJSON
实例,并在那里的Para
上执行此转换,但我无法覆盖该实例,因为它已经定义好了!我愿意接受一个实际上不涉及Para
类型本身的解决方案,我只需要一种将更多数据耦合到Para
而不丢失完整Pandoc
文档的任何结构的方法。
但是我无法覆盖实例,因为它已经定义好了!
您可以定义包装Pandoc的newtype,然后为此定义一个自定义ToJSON实例。CCD_ 9和CCD_。
您可能会考虑的另一件事是创建一个函数,将每个Para封装在Div中,并将字符串存储在其一个属性中。从你所说的内容中还不清楚这是否符合你的目的,但定义一个进行这种转换的函数很容易。
JSON
序列化程序可能是最好的方法。您可以在不使用typeclass机制的情况下定义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是在一种注释上参数化的,例如haskell-src-exts,或者使用一些开放的固定点设计,这将允许更聪明的东西)。
一种相当粗糙的方法是使用toJSON
进行序列化,只找到JSON
结构中要注释的部分,只反序列化该部分并计算注释,保留,然后添加计算的注释。非常丑陋,但我认为你不必重新实现任何序列化程序。如果pandoc有很多递归构造函数,或者非常复杂的序列化,我可能会考虑这一点,但目前我可能只是咬紧牙关,重新实现递归情况。