這是可怕的,你絕對不應該這樣做。 unsafeCoerce
這裏可能會返回不同的值,取決於表達式是否已經被評估過,如果GC決定移動對象(並且GHC有一個壓縮收集器AFAIK,這樣就會一直髮生),甚至可能依賴於沒有任何東西的對象通過閱讀結束來處理它。可怕的,可怕的想法,這。
參照平等的測試,就像你在最命令式語言看
var foo = Object();
var bar = Object();
foo === foo // true
foo === bar // false
是不可能在Haskell,因爲引用透明,它說,你可以隨時替換其定義,什麼都不會變更改。如果它不被命名的語言有引用透明,你可以用替換代碼:
Object() === Object() // true
Object() === Object() // false
這顯然是一個矛盾。引用透明是使Haskell如此高興的事情之一,但不幸的是,如果我推斷你正在嘗試做什麼,它將會使它變得不可能。我建議不要繞開參考透明度(你可以使用unsafePerformIO
) - Haskell 極其如果沒有它,很難推理 - 整個語言都是圍繞這個假設建立的。
所以,有了這個警告,這裏有一些筆記,無論如何funzies,因爲我已經下了這個特殊的兔子洞。
它看起來像我在模擬從Id
到它們所指的對象的地圖,而且這個地圖可以是多態的。即也許你想喜歡的功能:與???
一些合適的值,因爲我們已經忘記了類型信息這是不可能的
insert :: SomeClass a => a -> MyMap -> (SomeId, MyMap)
lookup :: MyMap -> SomeId -> ???
。你可以使用Data.Dynamic
,我想:
lookup :: MyMap -> SomeId -> Maybe Dynamic
根據你想要做什麼。這將涉及很多鑄造,你基本上是通過這樣做把靜態類型安全性扔出窗外。
也許你想考慮鍵入標識符?
insert :: SomeClass a => a -> MyMap -> (SomeId a, MyMap)
lookup :: MyMap -> SomeId a -> Maybe a
如果你有SomeClass
需要一些獨特的「哈希」生成功能(它是真正保證是甚至跨類型獨特的),那麼你可以使這個API的工作。如果發生衝突,那麼出現錯誤unsafeCoerce
錯誤(例如,在ghci中嘗試unsafeCoerce 42 "foo" :: String
)。您可以通過在您的Id類型中添加TypeRep
來緩解一些痛苦,但您仍然必須自行決定如何對這些值進行哈希處理。
你可以用新生成的Unique
時,你的密鑰對的值,使用unsafePerformIO
,但你會違反參照透明度,如果你這樣做,因爲如果你生成具有相同值的兩個鍵,就會比較不同,這在純語言中是無稽之談。
基本上,一個異構地圖的整個想法是困難的。
我寫了hetero-map
,它實現了一個類型安全的異構映射,更像一個關於這個想法如何輕浮而不是一個有用模塊的藝術作品。但是,嘿,讓我知道如果你發現它的用處。 ;-)
也許你應該退後一步,描述你正試圖解決的更大問題,以至於你覺得你需要這個。我向你保證有一個更好的方法。
'HashMap'鍵不需要'Ord' - 只有'Map'。你究竟在做什麼? – Alec