Haskell 从受数据类型约束的存在类型检索信息

Haskell 从受数据类型约束的存在类型检索信息,haskell,existential-type,data-kinds,Haskell,Existential Type,Data Kinds,如果我有一个受有限的DataKind {-# LANGUAGE DataKinds #-} data K = A | B data Ty (a :: K) = Ty { ... } 还有一种存在类型,它忘记了类型中K的精确选择。。。但是在过去的字典里记得 class AK (t :: K) where k :: Ty t -> K instance AK A where k _ = A instance AK B where k _ = B data ATy where ATy :

如果我有一个受有限的
DataKind

{-# LANGUAGE DataKinds #-}

data K = A | B

data Ty (a :: K) = Ty { ... }
还有一种存在类型,它忘记了类型中
K
的精确选择。。。但是在过去的字典里记得

class AK (t :: K) where k :: Ty t -> K
instance AK A where k _ = A
instance AK B where k _ = B

data ATy where ATy :: AK a => Ty a -> ATy
确实是这样的,
ATy(tya)(tyb)
,但如果我想写其中一个证人,我需要使用
unsecfectorece

getATy :: ATy -> Either (Ty A) (Ty B)
getATy (ATy it) = case k it of
  A -> Left  (unsafeCoerce it)
  B -> Right (unsafeCoerce it)

因此,一般来说,这是可行的——我可以忘记使用
ATy
选择
K
,并使用
getATy
部分记住它。总之,这充分利用了尽可能多的类型信息

然而,这种类型的信息感觉好像如果做得正确,它应该是“明显的”


有没有一种方法可以在不使用
unsafeccerce
的情况下实现上述目标?有没有办法摆脱存在论中的那种约束?是否可以完全基于数据类型提供的信息约束来执行此技术?

如果要对存在类型进行运行时案例分析,还需要单例表示:

{-# LANGUAGE DataKinds, GADTs, KindSignatures, ScopedTypeVariables #-}

data K = A | B

-- runtime version of K. 
data SK (k :: K) where
    SA :: SK A
    SB :: SK B

-- ScopedTypeVariables makes it easy to specify which "k" we want. 
class AK (k :: K) where
    k :: SK k 

instance AK A where k = SA
instance AK B where k = SB

data Ty (a :: K) = Ty

data ATy where
    ATy :: AK k => Ty k -> ATy

getATy :: ATy -> Either (Ty A) (Ty B)
getATy (ATy (ty :: Ty k)) = case (k :: SK k) of
    SA -> Left ty
    SB -> Right ty
这里可以使用
singleton
包来删除样板文件:

{-# LANGUAGE DataKinds, GADTs, TypeFamilies, TemplateHaskell, ScopedTypeVariables #-}

import Data.Singletons.TH

$(singletons [d| data K = A | B |])

data Ty (a :: K) = Ty

data ATy where
    ATy :: SingI k => Ty k -> ATy

getATy :: ATy -> Either (Ty A) (Ty B)
getATy (ATy (ty :: Ty k)) = case (sing :: Sing k) of
    SA -> Left ty
    SB -> Right ty
关于你的最后一个问题:

有没有办法摆脱存在论中的AK约束? 这项技术能否完全基于信息来执行 数据类型提供的约束

只要我们有一个数据类型作为一个类型参数,信息在运行时就不存在,我们不能对它进行任何分析。例如,以这种类型为例:

data ATy where
    ATy :: Ty k -> ATy
我们永远不能在
tyk
中实例化
k
;它必须保持多态性

提供运行时类型信息有多种方式;隐式传递字典是一种选择,如我们所见:

data ATy where
   ATy :: AK k => Ty k -> ATy
这里,
akk
只是一个指向
SK
的指针(因为
akk
类只有一个方法,我们没有该类的字典,只有一个指向该方法的普通指针),构造函数中的一个额外字段。我们也可以选择使该字段显式:

data ATy where
    ATy :: SK k -> Ty k -> ATy
运行时的表示形式也差不多

第三种选择是使用GADT构造函数对类型进行编码:

data ATy where
    ATyA :: Ty A -> ATy
    ATyB :: Ty B -> ATy

这个解决方案在性能方面非常好,因为没有空间开销,因为构造函数已经对类型进行了编码。它就像一个带有隐藏类型参数的

Ahm
A->Left Ty
?啊,呃,让我改变这个例子,让它变得不那么琐碎。哎呀!
K
类型可能是幻影,但它仍然传递大量信息。
AK
类没有使用我的GHC 7.8编译,因为
K
的类型没有提到任何类类型变量。输入错误,很抱歉:
a->t
啊,所以单例GADT具有我们需要的类型平等性。这就是我的作品missing@J.Abrahamson我添加了一些关于可选类型表示的注释。非常好,谢谢你提供的信息。这正是我所缺少的。