在GADT构造函数中约束类型

时间:2017-05-24 20:23:01

标签: haskell dependent-type type-constraints gadt type-families

我有一个简单的ADT

data Concept a = Entity  a |  Role a | Relation a | Resource a | Sub (Concept a)

现在我想使用这个ADT创建一个GADT,它将限制它的构造函数的类型签名。这段代码不起作用,但我想做这样的事情:

data Construct a b where
      Has :: Concept a -> 'Resource b -> Construct (Concept a) ('Resource b)

即。 Has的{​​{1}}构造函数可以将第一个类型的参数作为任何形式的Construct,但第二个类型参数应该是Concept构造函数(提升为类型)。此签名失败,因为我使用类型代替类型。但是我想要意识到这样的事情并没有完全解决如何做同样的问题。

我正在导入Resource

编辑:

基于一条评论,如果我这样做

{-# LANGUAGE GADTs, TypeInType #-}

然后是类型检查。但是现在如何在 data Construct (a :: Concept ak) (b :: Concept bk) where Has :: Construct a ('Resource b)

上进行模式匹配时提取值
Has

我的要求是我想约束f :: Construct a b -> T.Text f Has = ??? 构造函数的类型,以便它只允许Has a b(即任何概念)和a :: Concept ak [1](即只有概念的资源类型) )例如

(b ~ 'Resource *) => (b :: Concept bk)

[1] - 在阅读了“种类中的约束”,“家庭类型”和“单身类型,我想通过这些原则可以实现这种约束。但我完全无法让它发挥作用

1 个答案:

答案 0 :(得分:3)

感谢#haskel-beginners的Cale,通过引入幻像类型并在Concept GADT

中对其进行标记来建议此解决方案
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}

data ConceptType = EntityT | RoleT | RelationT | ResourceT | SubT ConceptType

data Concept (t :: ConceptType) a where
  Entity :: a -> Concept EntityT a
  Role :: a -> Concept RoleT a
  Relation :: a -> Concept RelationT a
  Resource :: a -> Concept ResourceT a
  Sub :: Concept t a -> Concept (SubT t) a

data Construct t a b where
  Has :: Concept t a -> Concept ResourceT b -> Construct t a b