我可以使用unsafecorce作为存在类型类的hashkey/comaprison键吗?

dar*_*ior 1 dictionary haskell

所以,如果我想创建一个hashmap键,例如使用存在类型

data SomeId = forall a. SomeClass a => SomeId a
Run Code Online (Sandbox Code Playgroud)

所以,如果我想创建一个地图,我需要自己实现Ord.有没有办法存储价值?在这种情况下,是unsafeCooerceInt永久性还是有任何警告?

像这样?

instance Ord SomeId where
    compare (Id a) (Id b) = compare (unsafeCoerce a)::Int (unsafeCoerce b)::Int
Run Code Online (Sandbox Code Playgroud)

有一个更好的方法吗?

Ale*_*lec 5

我不清楚你在寻找什么(也可能不是你).以下是如何实现EqHashable存在的数据类型.

你需要在存在主体上添加一个Hashable,Typeable和一个Eq约束(除了你想要的其他约束之外 - 我将使用它Show).

import Data.Typeable
import Data.Hashable

data SomeId = forall a. (Show a, Hashable a, Eq a, Typeable a) => SomeId a

-- This instance uses the fact 'SomeId' wraps types that have and 'Eq' and 
-- a 'Typeable' constraint
instance Eq SomeId where
  SomeId a == SomeId b = maybe False (a ==) (cast b)

-- This instance uses the fact 'SomeId' wraps types that have 'Hashable' constraints
instance Hashable SomeId where
  hashWithSalt s (SomeId a) = 0xdeadbeef * hashWithSalt s a
Run Code Online (Sandbox Code Playgroud)

并且,出于调试目的:

instance Show SomeId where
  show (SomeId x) = show x
Run Code Online (Sandbox Code Playgroud)

现在,我可以SomeId用作一个关键HashMap.例如,

ghci> import qualified Data.HashMap.Strict as H
ghci> hashMap = H.fromList [(SomeId 1, "one"), (SomeId (), "unit"), (SomeId "s", "string")]
ghci> H.lookup (SomeId 1) hashMap
Just "one"
ghci> H.lookup (SomeId ()) hashMap
Just "unit"
ghci> H.lookup (SomeId "s") hashMap
Just "string
ghci> H.lookup (SomeId 2) hashMap
Nothing
ghci> H.lookup (SomeId True) hashMap
Nothing
Run Code Online (Sandbox Code Playgroud)

作为最后的评论:请注意你所施加的初始约束SomeId,Typeable并且Eq都是可导出的,因此满足这些界限并不像最初看起来那么困难.


如果不清楚,我告诉你一个替代你的unsafeCoerce.这种方法是......不可取的.特别是它

  • 一般违反参考透明度
  • 完全无视所有的法律EqOrd

简而言之 - 它将无法工作,即使它确实如此,也会造成一大堆难以复制和混淆的错误.