我将以这种方式覆盖动态数据类型的相等类:
instance Eq Dynamic where
x==y = dynamicEq x y
dynamicEq :: Dynamic -> Dynamic -> Bool
dynamicEq x y = ConstrName x == ConstrName y && sameSlots(slots x)(slots y)
where
sameSlots [] [] = True
sameSlots ((x::Eq a => a):xs)(y:ys) = x == fromDynamic y && sameSlots xs ys
你可以为我命名或声明任何可以返回 ConstrName 和 slots 值的函数吗?也许使用Tycon或类似的东西?
答案 0 :(得分:1)
从不摆弄这些东西,但这可能是两个部分答案,这对你来说已经足够了。我担心这不是一般解决方案,也不是制作Dynamic
和Eq
实例的方法(如果很容易的话,它可能就是一个)。
但是在你的上一条评论中你说过你只想比较自己的类型。所以,部分回答1:
如果您猜测它们的类型,您当然可以比较两个Dynamics
。例如:
eqInt :: Int -> Int -> Bool
eqInt = (==)
x = toDyn (3::Int)
y = toDyn (3::Int)
z = toDyn (4::Int)
compareDynamic :: (Typeable a, Eq a) =>
(a -> a -> Bool) ->
Dynamic -> Dynamic -> Maybe Bool
compareDynamic eq x y = do
let dEq = toDyn eq
fn1 <- dynApply dEq x
res <- dynApply fn1 y
fromDynamic res
现在:
...> compareDynamic eqInt x y
Just True
...> compareDynamic eqInt x z
Just False
然而,尽管compareDynamic
具有误导性的多态类型,但您只能传递单态比较函数。参见:
...> compareDynamic (==) x z
Nothing
我想这是因为类型系统无法知道它应该在这里使用哪个(==)
实例。我保持compareDynamic
多态,因此您不必为每种类型创建单独的函数。
现在,既然您只想比较自己的类型,那么您可以按顺序查看比较函数列表:
eqs = [eqMyTypeA, eqMyTypeB, eqMyTypeC]
comp dynA dynB = catMaybes $ map (\eq -> eq dynA dynB) eqs
并且[]
表示两种不同的类型,[Just False]
相同的类型具有不同的值,[Just True]
具有相同的类型和值。
如果您有大量类型,您还可以在进行任何比较之前确定构造函数(这是部分答案2)并根据它选择正确的函数。它的构造函数不同,你根本不需要尝试比较:
constructor :: Dynamic -> TyCon
constructor = typeRepTyCon . dynTypeRep
并且有一个查找表,将构造函数与相等函数匹配。
一句结束语:如果你需要,请三思而后行。如果你需要Dynamic
,请多考虑三次,大多数Haskell程序都没有。是不只是Java思维偷偷摸摸?