在Haskell Libraries邮件列表上讨论Void
时,有this remark:
在过去的那一天,它曾由
unsafeCoerce
执行 Conor McBride谁不想为遍历整个Functor
付出代价 并且当类型告诉我们它不应该有时,替换它的内容 任何。如果应用于适当的Functor,这是正确的,但在 存在GADT。
unsafeVacuous
的文档也说:
如果
Void
无人居住,那么只保留Functor
类型值的任何Void
都没有值。这对于有效仿函数只能对参数执行类似GADT的分析。
这样一个淘气的GADT Functor
实例怎么样? (当然只使用总函数,没有undefined
,error
等。)
答案 0 :(得分:4)
如果您愿意提供一个不符合仿函数法律的Functor
实例,那当然是可能的(但总计):
{-# LANGUAGE GADTs, KindSignatures #-}
import Data.Void
import Data.Void.Unsafe
data F :: * -> * where
C :: F Void
D :: F a
instance Functor F where
fmap f _ = D
wrong :: ()
wrong = case (unsafeVacuous C :: F Int) of D -> ()
现在评估wrong
会导致运行时异常,即使类型检查器将其视为总计。
因为关于functoriality的讨论太多了,所以让我添加一个非正式的论证,为什么实际对其论证进行分析的GADT不能成为一个仿函数。如果我们有
data F :: * -> * where
C :: ... -> F Something
...
其中Something
是任何不是普通变量的类型,我们无法为Functor
提供有效的F
实例。 fmap
函数必须将C
映射到C
才能遵守仿函数的身份法。但我们必须为未知F b
生成b
。如果Something
不是普通变量,那么这是不可能的。