我在一个使用两个IntMaps的文档中有一条记录:
data Doc = Doc { kernels :: IntMap Kernel, nodes :: IntMap Node }
Run Code Online (Sandbox Code Playgroud)
但是我发现来自两个IntMaps的键具有不同的含义,并且我无法在两种不同类型中分离,并且在混合内核类型和节点类型时不会出错.我想要有从内核映射和节点映射检查密钥的函数,并且不允许混淆.例如:
someFunction :: Doc -> KernelKey -> NodeKey -> a
someFunction doc k1 k2 = .....
Run Code Online (Sandbox Code Playgroud)
而不是当前:
someFunction :: Doc -> Int -> Int -> a
someFunction doc k1 k2 = .... -- warning check twice k1 and k2
Run Code Online (Sandbox Code Playgroud)
它可以吗?或者我将IntMap
改为Map
.
谢谢
ham*_*mar 11
您可以使用newtype
包装Int
来区分它们的含义.
newtype KernelKey = KernelKey Int
newtype NodeKey = NodeKey Int
someFunction :: Doc -> KernelKey -> NodeKey -> a
someFunction doc (KernelKey k1) (NodeKey k2) = ...
Run Code Online (Sandbox Code Playgroud)
这样,你仍然可以在IntMap
内部使用,但是暴露一个更加类型安全的接口,特别是如果你还控制KernelKey
和NodeKey
值的创建方式,即你不导出它们的构造函数,这样用户只能将它们作为其他函数的返回值.
请注意,newtype
包装器在运行时会消失,因此这种额外的包装和展开不会以任何方式影响性能.