访问构造函数名称和参数

时间:2013-08-20 18:50:22

标签: haskell dynamic equals

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

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或类似的东西?

1 个答案:

答案 0 :(得分:1)

从不摆弄这些东西,但这可能是两个部分答案,这对你来说已经足够了。我担心这不是一般解决方案,也不是制作DynamicEq实例的方法(如果很容易的话,它可能就是一个)。

但是在你的上一条评论中你说过你只想比较自己的类型。所以,部分回答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思维偷偷摸摸?