来自通用整数表达式的 TypeLit

TypeLit from generic Integer expression

我知道构造 Nat 的唯一方法是将 -XDataKinds 与提升的整数一起使用,即 type MyInt = 10 :: Nat.

相反,我想要一个函数

foo :: Integer -> Integer

我可以用反映的 Nat 索引,然后 reify 结果。为了证明我的意思,假设一些函数 mkNat :: Integer -> Q Type。我要写

type Z = $(mkNat $ foo $ natVal (Proxy::Proxy 10))

(在我的示例中,foo 足够快,可以在编译时计算它而无需过多的开销。)拥有此功能可以节省 运行 [=17 的多步骤过程=] 在单独的 GHCi 会话中,然后将结果的十进制表示形式复制到源文件中,然后编译我真正想要的代码。

当然,唯一缺少的部分是 mkNat。如果我编写自己的自定义数据类型,mkNat 的等效项很容易编写。但我真的很想使用内置的 TypeLits。是否有一些 TemplateHaskell(或单例,或其他魔法)允许我将任意 Integer 表达式具体化为 Nat

是的!

{-# LANGUAGE DataKinds       #-}
{-# LANGUAGE TemplateHaskell #-}

module Main where

import Data.Proxy
import GHC.TypeLits
import Splices

type Z = $(mkNat $ natVal (Proxy :: Proxy 10))

然后:

module Splices where

import Language.Haskell.TH

mkNat :: Integer -> Q Type
mkNat = return . LitT . NumTyLit