举个简单的例子,假设我想要一个类型来表示井字游戏标记:
data Mark = Nought | Cross
与 Bool
相同Prelude> :info Bool
data Bool = False | True -- Defined in ‘GHC.Types’
但是没有Coercible Bool Mark
他们之间,即使我导入 GHC.Types
(我首先认为 GHC 可能需要 Bool
的定义位置可见),拥有此实例的唯一方法似乎是通过 newtype
.或许我可以定义
newtype Mark = Mark Bool
并定义 Nought
和 Cross
对于双向模式,我希望有比这更简单的东西。
最佳答案
不幸的是,你运气不好。作为documentation for Data.Coerce
explains , “可以假设存在以下三种实例:”
instance Coercible a a
,instance Coercible a a' => Coercible (Maybe a) (Maybe a')
, 和此外,“尝试手动声明
Coercible
的实例是一个错误”,这就是你所得到的。任意不同的数据类型之间没有实例,即使它们看起来相似。这可能看起来令人沮丧,但考虑一下:如果有一个
Coercible
Bool
之间的实例和 Mark
,是什么阻止它强制 Nought
至True
和 Cross
至False
?可能是Bool
和 Mark
在内存中以相同的方式表示,但不能保证它们在语义上足够相似以保证 Coercible
实例。您使用新类型和模式同义词的解决方案是解决问题的一种很好、安全的方法,即使它有点烦人。
另一种选择是考虑使用
Generic
.例如,查看 genericCoerce
的想法来自 this other question
关于haskell - 是否可以在自定义类型和标准库类型之间建立强制实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66309171/