Haskell-操作/扩展不在您控制范围内的ADT



操作/扩展不在您控制范围内的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的案例,如BlockQuoteOrderedList等。对于其他案例,您可以直接转发到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有很多递归构造函数,或者非常复杂的序列化,我可能会考虑这一点,但目前我可能只是咬紧牙关,重新实现递归情况。

最新更新