假设我已使用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中哪个无效。有可能这样做吗?
答案 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”发布时,我们将拥有较少的繁琐工具。目前,单身人士工作,但有时很麻烦。不过,目前,我们仍必须使用它们。