举一个简单的例子,假设我想要一个类型来表示井字游戏标记:
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
and Cross
对于双向模式,我希望有比这更简单的东西。
不幸的是,你运气不好。作为的文档Data.Coerce解释 http://hackage.haskell.org/package/base-4.14.1.0/docs/Data-Coerce.html#t:Coercible,“可以假装存在以下三种实例:”
-
自实例,如instance Coercible a a
,
-
用于在数据类型的两个版本之间进行强制转换的实例,这两个版本因具象或幻像类型参数而异,如下所示instance Coercible a a' => Coercible (Maybe a) (Maybe a')
, and
-
新类型之间的实例。
此外,“尝试手动声明一个实例Coercible
是一个错误”,所以这就是您得到的全部内容。任意不同的数据类型之间不存在实例,即使它们看起来相似。
这可能看起来令人沮丧,但请考虑一下:如果有一个Coercible
之间的实例Bool
and Mark
,是什么阻止了它强制Nought
to True
and Cross
to False
?可能是这样Bool
and Mark
在内存中以相同的方式表示,但不能保证它们在语义上足够相似以保证Coercible
实例。
使用新类型和模式同义词的解决方案是解决该问题的一种很好、安全的方法,即使它有点烦人。
另一种选择是考虑使用Generic
。例如,看看这个想法genericCoerce
from 这另一个问题 https://stackoverflow.com/questions/66011340/ensuring-that-two-gadts-have-the-same-underlying-representation-in-ghc-haske/66021612#66021612
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)