这是可怕的,你绝对不应该这样做。 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