2013-05-18 50 views
1

模块A出口模块B和C重叠实例的肮脏破解?

模块B出口实例X

模块C出口实例ý

X和Y是一个普通类型的类的实例。

实例X和Y的类型完全相同,即完全重叠。

当我单独使用B或C时,一切正常。当我导入它们(这里是A)进行一些比较测试(或基准测试)时,我在C语言中发现重叠的实例错误,说X和Y都匹配。

这令我感到困惑,因为从C到X的唯一路径是:C -> A -> B。这是应该如何?另外,有没有办法解决这个问题?对于肮脏的黑客行为我没有问题,因为这两个实例在正常情况下从不一起使用。特别是,我不想引进幻影类型等

+3

你不需要从C到X的路径,你需要一个从C到X的路径到一个公共会场。这是A。实例总是被导出,所以在A中,你有两个实例在范围内。唯一理智的方法是不要为相同类型使用同一类的两个实例。 (如果B和C都是你的,请修复它!如果其中一个是你的,另一个不是的话,你能摆脱你的实例并使用另一个吗?如果这两者都不是你的,请戳包的维护者以便明智地解决它) –

+0

他们都是我的,只是我希望保留的两个替代实现。我知道我可以使用幻像类型来解决这个问题,但最终,这会使事情变得复杂,在我的情况下会导致更多噪音语法(类型类用作DSL的一部分)。在Scala中,可以选择导入哪些实例,所以我认为必须有一些方法。 – letmaik

回答

2

根据你所拥有的班上有模样,它应该很容易用两个小代理模块PQ,每个具有相同newtype ProxyXY解决这个问题与GeneralisedNewtypeDeriving包装到所需的类;但一个导入module B和另一个导入module C,所以他们实际上使用不同的实例。然后,您有两种类型P.ProxyXYQ.ProxyXY,它们的行为相同,但前者使用X实例,而后者使用基础类型的Y实例。

(如果这就是你的意思与“幻影类型”,但这些实际上是something different不舒尔)

+0

嗯,班级是'可重写的r a b ...'我尝试过'newtype ProxyXY p = ProxyXY p派生(Rewritable p)'但它说“不能派生'可重写p(ProxyXY p)'的实例(即使有狡猾的newtype派生):'Rewritable p'会没有神性1“。顺便说一下,您的答案与[this]相关(http://joyoftypes.blogspot.com/2012/02/haskell-supports-first-class-instances.html?showComment=1330615107602#c7037550684345333705)? – letmaik

+0

也许你应该提到它是你正在谈论的MultiParam类型的类!那么'GeneralisedNewtypeDeriving'不起作用。你仍然可以编写代理newtypes并手动定义它们的实例,但这当然不会很好。 – leftaroundabout

2

好吧,这不是一个严肃的回答,虽然它让我编译我的代码。

我觉得GHC(7.4.1)或cabal有一个bug。第一次编译失败,并声明重叠实例错误。但是,再次使用它(两次使用cabal-dev build)它成功!我将解释为什么:

第一次编译在编译C时停止。所以C和A没有编译。重新运行编译,首先编译C,成功,然后A.我猜C可以现在被编译,因为GHC不会从B中获取间接实例(因为C没有直接依赖于B,而A是编号 C)。

所以,最后,这是一个由部分编译引起的问题,对我的问题确实是一个非常肮脏的黑客攻击。