有没有办法说服GHC这个类型参数是幻像?

时间:2018-02-01 21:27:22

标签: haskell

请考虑以下代码:

{-# LANGUAGE DataKinds #-}  -- used to make it very clear that the param is phantom
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RoleAnnotations #-}
module Test where
data Triv = Triv
data F (f :: * -> *) (a :: Triv) = F (f (F f a))
type role F nominal phantom

我预计它会起作用,因为a的角色对我来说似乎很明显。但是:

/.../Test.hs:7:5: error:
    • Role mismatch on variable a:
        Annotation says phantom but role nominal is required
    • while checking a role annotation for ‘F’
Failed, modules loaded: none.

这是为什么?类型参数不是实际上是幻像(在某种意义上说,使用unsafeCoerceF Identity a转换为F Identity b可能会在运行时失败)?或者GHC的角色推理仅仅不能完成这项任务?并且,如果是后者,有没有办法说服GHC在这种情况下a实际上是幽灵?

2 个答案:

答案 0 :(得分:3)

这个角色实际上不是幻影。以下类型检查至少GHC 7.8.4:

{-# LANGUAGE DataKinds #-}  -- used to make it very clear that the param is phantom
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE TypeFamilies #-}
module Test where
import GHC.Exts
data Triv = Triv
data F (f :: * -> *) (a :: Triv) = F (f (F f a))

type family Bad a
type instance Bad (F f 'Triv) = Int
type instance Bad (F f Any) = Bool

x = 3 :: Bad (F f 'Triv)
y = True :: Bad (F f Any)

此漏洞在8.0版本发布时(可能在之前)被插入,但there are others似乎更为基础:

{-# LANGUAGE DataKinds #-}  -- used to make it very clear that the param is phantom
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE TypeFamilies #-}
module Test where
data Triv = Triv
data F (f :: * -> *) (a :: Triv) = F (f (F f a))

type family Succ :: Triv -> Triv

type family Bad a where
    Bad (F f 'Triv) = Int
    Bad (F f a) = Bool

x = 3 :: Bad (F f 'Triv)
y = True :: Bad (F f (Succ 'Triv))

如果你反对我不能写F Bad,那么它很容易解决;您可以将以下附录添加到前两个文件中的任何一个。

data BadData a = BadData (Bad a)
xF :: F BadData 'Triv
xF = F (BadData x)
yF :: F BadData (Succ 'Triv)
yF = F (BadData y)

答案 1 :(得分:1)

f的参数可能具有名义角色。我需要Triv种至少有两个居民来展示反例。

data Triv = T1 | T2

data family K a :: *
data instance K (F K T1) = K1 Int Int
data instance K (F K T2) = K2 Double

coerce :: F K T1 -> F K T2
-- i.e., K (F K T1) -> K (F K T2)
-- That should not typecheck.