2011-08-01 3 views
5

私は2つのIntMaps使用した文書のレコードがあります。異なるキータイプでIntMapを使用するには?

data Doc = Doc { kernels :: IntMap Kernel, nodes :: IntMap Node } 

をしかし、私は両方のIntMapsから鍵が異なる意味を持っていることを発見し、私は2つの貴様の種類に分離するために失敗したときにミックスエラーを得ることはありませんカーネルタイプとノードタイプ。私は、カーネルマップとノードマップからキーをチェックする機能を持ち、ミックスアップを許可しません。例えば:

someFunction :: Doc -> KernelKey -> NodeKey -> a 
someFunction doc k1 k2 = ..... 

代わりの現在:

someFunction :: Doc -> Int -> Int -> a 
someFunction doc k1 k2 = .... -- warning check twice k1 and k2 

はそれがかのうですか?またはIntMapからMapに変更します。

おかげ

+1

'Map'の代わりに' IntMap'を使う理由は何ですか?パフォーマンスの場合は、 'unordered-containers'(これはあなたにとって最適な解決策かもしれませんが、考慮する価値があります)を考慮する必要があります。 –

+2

'IntSet'に関する関連する質問を参照してください。http://stackoverflow.com/questions/5746590/how-to-newtype-in​​tset ...あなたは[' enummapset'パッケージ](http: /hackage.haskell.org/package/enummapset)、これは私が現在使っているものです – hvr

答えて

10

あなたはその意味を区別するためにInt周りのラッパーを作るためにnewtypeを使用することができます。

newtype KernelKey = KernelKey Int 
newtype NodeKey = NodeKey Int 

someFunction :: Doc -> KernelKey -> NodeKey -> a 
someFunction doc (KernelKey k1) (NodeKey k2) = ... 

そのように、あなたはまだ、内部IntMapを使用していますが、より多くのタイプセーフなインターフェイスを公開、あなたもKernelKeyNodeKey値が作成されます方法を制御する場合は特に、あなたがユーザーように、自分のコンストラクタをエクスポートしない、つまりすることができ他の関数からの戻り値としてのみ取得します。

実行時にnewtypeラッパーが表示されなくなるため、この余分なラッピングとアンラッピングはパフォーマンスに何らかの影響を与えません。

+0

私はパフォーマンスについて混乱していました。しかし、ラッパーが実行時に消えたら、私はあなたのソリューションを使用します。 – Zhen

3

統一されたキータイプを作成し、DocタイプのIntMap APIをラップすることができます。このように見えるかもしれません。

このソリューションの素晴らしい点は、必要なマップAPI関数を1つずつ必要とすることです。ここには、あなたが持っているコードに近い別の解決策があります。

newtype NodeKey = NodeKey Int 
newtype KernelKey = KernelKey Int 
lookupDocNode :: NodeKey -> Doc -> Maybe Node 
lookupDocKernel :: KernelKey -> Doc -> Maybe Kernel 

また、新しいタイプを使用せずにこの解決策を実行することもできます。これらのソリューションは両方とも型の安全性を提供します。最初のタイプでは、タイプで必要なものを指定する必要があります。 2番目の関数では、呼び出す関数を選択して指定します。

+0

私は統一されたキータイプが好きではありません。私は両方のキーを組み合わせた関数に問題があり、混乱する可能性があります:例えば 'lookupNodeHasKernel :: Int - > Int - > Bool' – Zhen

関連する問題