0

我将以这种方式覆盖动态数据类型的相等类:

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

你能命名或声明任何可以为我返回ConsrNameslot值的函数吗?也许使用 Tycon 或类似的东西?

4

1 回答 1

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 思想潜入吗?

于 2013-08-21T14:30:40.663 回答