我有一个情况,我现在正在使用非常可怕的函数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
两个额外的事情需要注意,是这些令牌,我用它来确保整数为他们供应是唯一一个单子内使用(即我不会做同样的标记两次)。我也使用一个全量化的阴影类型变量,就像ST monad一样,确保(假设只有我在模块中公开的方法被使用),没有办法返回一个标记(或者实际上甚至是F)从monad没有它是一个类型错误。我也不公开这个令牌构造函数。
我认为,据我所知,这应该是一个安全使用不安全的Coerce,正如我可以说的(我希望)相当高的信心,我强制的价值实际上正是我的类型我强迫它,但我可能是错的。我也尝试过使用Data.Typeable,它很好地工作,但目前我正在试图避免Typeable约束,特别是因为gcast似乎在很多方面都有类似的做法,而且我仍然需要令牌来区分不同的同类型的Fs。
非常感谢任何帮助/建议。
这看起来很像'Data.Typeable',它使用'unsafeCoerce'来实现'cast'。 –
这很像这样 - 事实上我在问题最后一段的后半部分曾经提到过iirc。不管怎么说,还是要谢谢你。 – DarkOtter
如果您有效地复制'cast',那么'unsafeCoerce'的使用是安全的,但是您确实会丢失编译器生成的'typeOf' /'TypeRep'。您可以考虑在您的令牌中使用“TypeRep”而不是“Integer”。 –