2013-05-18 77 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)。

所以,最後,這是一個由部分編譯引起的問題,對我的問題確實是一個非常骯髒的黑客攻擊。