从评估级别访问GADT约束

时间:2019-01-17 13:10:21

标签: haskell dependent-type gadt

假设我已使用DataKinds扩展名允许将数据提升为类型,则尝试从运行时开始使用GADT参数。即具有

data Num = Zero | Succ Num
data Something (len :: Num) where
  Some :: Something len

我想要功能

toNum :: Something len -> Num

对于任何Some :: Something n,它都会返回n

toNum (s :: Something n) = n

在Haskell中哪个无效。有可能这样做吗?

1 个答案:

答案 0 :(得分:5)

在Haskell中,这是不可能的,因为在运行时会删除类型。也就是说,程序运行时,内存中没有有关类型中索引let的值的信息。

为克服此问题,我们需要在运行时强制Haskell在内存中保留该值。通常使用 singleton 辅助类型完成此操作:

data Num = Zero | Succ Num

data SNum (n :: Num) where
   SZero :: SNum 'Zero
   SSucc :: SNum n -> SNum ('Succ n)

data Something (len :: Num) where
  Some :: SNum len -> Something len

使用它,您可以轻松编写

sToNum :: SNum n -> Num
sToNum SZero = Zero
sToNum (SSucc n) = Succ (sToNum n)

然后

toNum :: Something len -> Num
toNum (Some n) = sToNum n

如果您查找“ haskell单例”,则应该找到几个示例。甚至还有一个singletons库可以部分自动化。

如果/当“依赖的Haskell”发布时,我们将拥有较少的繁琐工具。目前,单身人士工作,但有时很麻烦。不过,目前,我们仍必须使用它们。