我想写一个xpickle,它将某些类型的值构造函数序列化为特定属性的XML属性值,并将XML属性值反序列化为值类型的构造函数。HXT xpickle(de)在属性值和值构造函数之间的序列化
我有如下数据:
module Main where
import Text.XML.HXT.Core
newtype Things = Things [Thing]
data Thing = Thing (Maybe Property)
data Property = A | B
someThings :: Things
someThings = Things [ Thing (Just A)
, Thing Nothing
, Thing (Just B)
]
而且我想连载弄成这个样子:
<things>
<thing property="a" />
<thing />
<thing property="b" />
</things>
下面是我采用的方法:
instance XmlPickler Things where
xpickle = xpWrap (\things -> Things things , \(Things things) -> things) $
xpElem "things" $
xpThings
xpThings :: PU [Thing]
xpThings = xpList xpickle
instance XmlPickler Thing where
xpickle = xpElem "thing" $
xpWrap (\p -> Thing p , \(Thing p) -> p) $
xpProperty
xpProperty :: PU (Maybe Property)
xpProperty = xpOption $ xpAttr "property" xpPropertyValue
xpPropertyValue :: PU Property
xpPropertyValue = xpAlt tag ps
where
tag A = 1
tag B = 2
ps = [ xpTextAttr "a"
, xpTextAttr "b"
]
main :: IO()
main = do
putStrLn $ showPickled [ withIndent yes ] someThings
return()
这里,xpProperty
创建或读取@property
属性,然后使用xpPropertyValue
来确定价值。 xpPropertyValue
根据值的构造函数值确定值:A
给出"a"
和B
给出"b"
并且使用xpTextAttr
函数构造这些值。这里的问题是,xpTextAttr
是String -> PU String
,我正尝试在需要PU Property
的地方使用它。但是我无法找到一种产生PU Property
值的替代方法,该值取决于值为Property
的值构造函数。
看起来'PU'没有'Functor'实例。当你编译这个时,你会得到:'没有使用'<$''产生的(Functor PU)实例。我不知道'PU'的'fmap'实现会做什么。 – ironchicken
啊,是的,因为它构造了一个可逆的解析器,从“PU字符串”到“PU属性”需要两个函数,每个函数都有一个函数。试试'xpWrap(const A)(const“a”)$ xpTextAttr a' – drquicksilver
仍然没有破解这个:将'xpAlt'的列表参数设为'[xpWrap(const A,const“a”)$ xpTextAttr“一个“,...]'导致串行化到''和一个'xpCheckEmptyAttributes:未处理的XML属性(s)检测到反序列化错误。”#: –
ironchicken