给定这个整数的包装器:
newtype MyProxy a = MyProxy Int
mkProxy :: Int -> MyProxy a
mkProxy a = MyProxy a
addProxy :: MyProxy a -> MyProxy a -> MyProxy a
addProxy (MyProxy a1) (MyProxy a2) = MyProxy $ a1+a2
我可以执行以下操作:
a = mkProxy 1
b = mkProxy 2
c = addProxy a b
因为幻影参数会统一。但我想阻止这种统一并导致在线类型错误c
。
ST monad 使用 rank2 类型来实现类似的效果。我可能可以通过更改addProxy
. 但我特别不想这样做。我想以a
某种方式注释类型变量以防止它在addProxy
调用中统一。
这在 Haskell 中可行吗?有没有理由说明这种选择会很危险?
编辑:
让我详细说明一个部分解决方案(需要-XScopedTypeVariables
)。我可以将上面的代码重写为:
c :: forall a1 a2. MyProxy a1
c = addProxy a b
where
a = mkProxy 1 :: MyProxy a1
b = mkProxy 2 :: MyProxy a2
这正确地导致类型错误,c
因为a1
并且a2
无法统一。但这有两个缺点:a
不能b
在顶层定义;并且您必须明确指定mkProxy
.
是否有可能解决这些缺点?