Haskell 存在论与证人再利用

Haskell 存在论与证人再利用,haskell,types,casting,existential-type,Haskell,Types,Casting,Existential Type,让我们假设我有一个存在主义类型T T = ∃X { a :: X, f :: X -> Int} 我创造了一个价值 v :: T v = pack {Int, { a = 0, f x = 0 } } as T 因此: 此值的用户被禁止知道实现中实际使用的是哪种类型的X。为了使用这个值,他们的代码在X 另一方面,实现者完全知道X实际上是一个Int,可以按照自己的意愿使用底层类型的容量 我想知道这种机制是否存在不破坏证据的变体: w, v = pack {Int, { a =

让我们假设我有一个存在主义类型T

T = ∃X { a :: X,  f :: X -> Int} 
我创造了一个价值

v :: T
v = pack {Int, { a = 0, f x =  0 } } as T
因此:

  • 此值的用户被禁止知道实现中实际使用的是哪种类型的
    X
    。为了使用这个值,他们的代码
    X
  • 另一方面,实现者完全知道
    X
    实际上是一个
    Int
    ,可以按照自己的意愿使用底层类型的容量
我想知道这种机制是否存在不破坏证据的变体:

w, v = pack {Int, { a = 0, f x =  0 } } as T
s = unpack w v  -- recovers type information 
其中,
w
将是将
X
连接到
int
的类型方程的值级证明。其想法是在代码的另一部分有选择地重用实现,并使用非多态代码。为了获得通常的存在行为,我们可以忽略返回的
w

我想人们可以将
X
转换为
Int
并放弃类型安全性,但这是另一回事:如果我知道
v
的秘密,那么我能够将秘密告诉其他人,并让编译器验证该秘密只被赋予的代码使用,这难道没有意义吗

是否尝试过/这其中最错误的部分是什么?

使用单例

-- singleton for some types we are interested in
data S a where
   Sint  :: S Int
   Sbool :: S Bool

-- existential type, with a singleton inside
data T where
   T :: S a -> a -> (a -> Int) -> T

-- producer
t :: T
t = T Sint 3 succ

-- consumer
foo :: T -> Int
foo (T Sint  n     f) = f (n + 10)
foo (T Sbool True  f) = 23
foo (T Sbool False f) = f 3
如果您需要填写完整的月份,请使用
Typeable

data T where
   T :: Typeable a => a -> (a -> Int) -> T

-- consumer
foo :: T -> Int
foo (T x f) = case cast x of
   Just n  -> f ((n :: Int) + 10)
   Nothing -> 12   -- more casts can be attempted here

打包一个GADT,它提供了一种通过模式匹配来学习存在量化类型的方法。这是一种模拟依赖对类型的方法


这是一个有用的折衷方案,但是消费者仍然需要通过对每种情况的词法分析来关注所有类型的实例化。将约束直接传递到作用域中如何?我不太理解您的问题,但我要说的是,可以使用hacky类隐式地生成
Ty
值:
class-Ty-a where-Ty::Ty-a
instance-Ty-Int-where-Ty=IntTy
instance-Ty-Char-where-Ty=CharTy
。然后,如果您愿意,可以打包隐式
TY
字典,而不是显式
TY
值:
datat,其中T::tya=>{x::a,f::a->Int}->T
。在我的示例中,我在第二行静态地知道
v
是由
Int
生成的。我不想通过模式匹配来输入一些词法范围来引入X=Int的证据。但这在一般情况下是不可能的,因为w是一个值,编译器需要执行代码来知道w的来源并引入相应的约束
data Ty a where
    IntTy :: Ty Int
    CharTy :: Ty Char

data T = forall a. T {
    ty :: Ty a,
    x :: a,
    f :: a -> Int
}

consumeT :: T -> Int
consumeT (T IntTy x _) = {-# GHC knows (x :: Int) in this branch #-} x + 3
consumeT (T CharTy x f) = {-# GHC knows (x :: Char) in this branch #-} f x + 3