我正在使用GHC.TypeLits
模块中的Nat
类型,它确实说程序员接口应该在一个单独的库中定义。在任何情况下,GHC.TypeLits
都有一个类KnownNat
,其类函数natVal
可将编译时间Nat
转换为运行时Integer
。还有一个类型函数(+)
,它增加了编译时间Nat
。
问题在于给定(KnownNat n1, KnownNat n2)
,GHC无法导出KnownNat (n1 + n2)
。
每当我添加类型级别自然时,都会导致需要添加的约束爆炸。
另一种选择是自己定义自然数字:
data Nat = Zero | Succ Nat
或者使用像type-natural这样的库。但是如果不使用内置于GHC中的Nats似乎很愚蠢,这也允许您很好地使用类型中的文字数字(即0
,1
)而不必定义:
N0 = Zero
N1 = Succ N0
etc...
是否存在围绕此问题的GHC KnownNat
限制在整个地方都需要?或者我应该忽略问题的GHC.TypeLits
模块?
答案 0 :(得分:10)
此GHC类型检查器插件正是这样做的(从已经可用的其他约束中获取“复杂”KnownNat
约束):https://hackage.haskell.org/package/ghc-typelits-knownnat
如果“类型检查器插件”听起来有点吓人(它最初对我有用),它实际上非常简单易用。只需将其作为依赖项添加到您的包文件(或cabal安装它),就像任何其他包一样,然后添加:
{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}
到源文件的开头(很像LANGUAGE
pragma),或者在包文件中全局添加它作为选项。
同一作者还有另一个插件,对于使用类型Nats非常有用:https://hackage.haskell.org/package/ghc-typelits-natnormalise。这个能够推断GHC本身所放弃的Nat类型表达式的相等性:像n + (m + 1) ~ (n + 1) + m
这样的东西,当GHC试图证明“预期”和“实际”类型匹配时,它会一直出现。< / p>