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)
有一个更好的方法吗?
我不清楚你在寻找什么(也可能不是你).以下是如何实现Eq和Hashable存在的数据类型.
你需要在存在主体上添加一个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.这种方法是......不可取的.特别是它
Eq和Ord简而言之 - 它将无法工作,即使它确实如此,也会造成一大堆难以复制和混淆的错误.