从评估级别访问 GADT 约束

Access GADT contstraint from evaluation level

我正在尝试使用运行时的一些 GADT 参数,假设我已经使用 DataKinds 扩展来允许将数据提升为类型。即有

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

我想要功能

toNum :: Something len -> Num

对于任何 Some :: Something n 将 return n:

toNum (s :: Something n) = n

在 Haskell 中无效。可以这样做吗?

在 Haskell 中这是不可能的,因为类型在 运行 时被删除。即当程序将运行时,内存中没有关于类型中索引let的值的信息。

为了克服这个问题,我们需要强制 Haskell 在 运行 时间将那个值保存在内存中。这通常使用 单例 辅助类型来完成:

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",您应该会找到几个示例。甚至还有一个 singletons 库来部分自动化。

如果/当 "dependent Haskell" 发布时,我们将可以使用不那么笨重的工具。目前,单身人士可以工作,但有时会很麻烦。不过,目前,我们必须使用它们。