我有一种情况,我目前正在使用极其可怕的功能 unsafeCoerce。幸运的是,这不是什么重要的事情,但我想知道这是否是对这个函数的安全使用,或者是否会有另一种方法来解决其他人知道的这个特定问题。
我拥有的代码如下所示:
data Token b = Token !Integer
identical :: Token a -> Token b -> Bool
identical (Token a) (Token b) = a == b
data F a = forall b. F (Token b) (a -> b)
retrieve :: Token b -> F a -> Maybe (a -> b)
retrieve t (F t' f) = if identical t t' then Just (unsafeCoerce f) else Nothing
需要注意的另外两件事是,这些标记在一个 monad 中使用,我使用它来确保为它们提供的整数是唯一的(即我不会两次制作相同的标记)。我还使用了一个 forall 量化的影子类型变量,与 ST monad 一样,以确保(假设仅使用我在模块中公开的方法)没有办法返回令牌(或者实际上什至是F) 来自 monad,而不是类型错误。我也没有公开令牌构造函数。
我认为,据我所见,这应该是 unsafeCoerce 的安全用法,正如我可以说(我希望)非常自信地说,我强制的值实际上正是我强制它的类型,但我可能错了。我也尝试过使用 Data.Typeable,它工作得很好,但目前我正在尝试这样做以避免 Typeable 约束,特别是因为 gcast 似乎在许多方面做了类似的事情,而且我仍然需要令牌来区分同类型的不同F。
非常感谢任何帮助/建议。