Haskell 为什么可以';我们不能定义封闭数据族吗?

Haskell 为什么可以';我们不能定义封闭数据族吗?,haskell,type-families,injective-function,Haskell,Type Families,Injective Function,所有以下工作: {-# LANGUAGE TypeFamilies #-} type family TF a type instance TF Int = String type instance TF Bool = Char data family DF a data instance DF Int = DFInt String data instance DF Bool = DFBool Char type family CTF a where CTF Int = String

所有以下工作:

{-# LANGUAGE TypeFamilies #-}

type family TF a
type instance TF Int = String
type instance TF Bool = Char

data family DF a
data instance DF Int = DFInt String
data instance DF Bool = DFBool Char

type family CTF a where
  CTF Int = String
  CTF Bool = Char
  CTF a = Double     -- Overlap OK!
…但事实并非如此(截至GHC-8.2):

(这里我只是猜测,但我想分享一下这个想法。)

假设我们能写

data family CDF a where
  CDF Int = CDFInt String
  CDF Bool = CDFBool Char
  CDF a = CDFOther Double
现在,这个定义所产生的值构造函数的类型是什么?我很想说:

CDFInt   :: String -> CDF Int
CDFBool  :: Char   -> CDF Bool
CDFOther :: Double -> CDF a
。。。但最后一个感觉很不对,因为我们会

CDFOther @ Int :: Double -> CDF Int
这是不允许的,因为在一个封闭的数据族中,
CDF Int
的(非底部)值必须以
CDFInt
构造函数开头

也许合适的类型是

CDFOther :: (a /~ Int, a /~ Bool) => Double -> CDF a
涉及“不平等约束”,但这将需要GHC现有的更多打字机制。我不知道类型检查/推断是否会在这种扩展中保持可判定性


相比之下,类型族不涉及值构造函数,因此这里不会出现这个问题。

封闭的数据族不是GADT吗?@davidyong很有趣。但是我想如果你使用GADT,在
CDF Int
中你可以找到
字符串或
双精度
。对于一个封闭的数据族,只能使用
字符串
。@ch当然,这就是我的意思。证据在GADT中以另一种方式流动,并且运行时表示方式非常不同。这听起来很有可能。这非常有意义。仍然想知道这是否是官方原因。假设每个数据族都有一个神奇的类型族,在这里实例化为
type FamilyOf CDF a::Nat,其中{FamilyOf CDF Int=1;FamilyOf CDF Bool=2;FamilyOf CDF=3}
。现在您可以为数据族构造函数指定类型:
CDFInt::FamilyOf CDF a~1=>String->CDF a
CDFBool::FamilyOf CDF a~2=>Char->CDF a
,以及
CDFOther::FamilyOf CDF a~3=>Double->CDF a
。我不知道这是否会遇到一些麻烦,但闻起来方向是正确的。在我最后的评论中,我的意思是“对于每个封闭的数据家族”。
CDFInt   :: String -> CDF Int
CDFBool  :: Char   -> CDF Bool
CDFOther :: Double -> CDF a
CDFOther @ Int :: Double -> CDF Int
CDFOther :: (a /~ Int, a /~ Bool) => Double -> CDF a