我知道构建Nat
的唯一方法是将-XDataKinds
与提升的整数一起使用,即type MyInt = 10 :: Nat
。
相反,我想要一个功能
foo :: Integer -> Integer
我可以使用反映的Nat
进行索引,然后 reify 结果。为了证明我的意思,假设一些函数mkNat :: Integer -> Q Type
。我想写
type Z = $(mkNat $ foo $ natVal (Proxy::Proxy 10))
(在我的示例中,foo
足够快,可以在编译时计算而不会产生过高的开销。)具有此功能可以省去在单独的GHCi中运行foo
的多步骤过程session,然后将结果的十进制表示复制到源文件中,然后编译我真正想要的代码。
当然唯一缺少的组件是mkNat
。如果我编写自己的自定义数据类型,则相当于mkNat
很容易编写。但我真的很想使用内置的TypeLits。是否有一些TemplateHaskell(或单例,或其他一些魔法)允许我将任意Integer
表达式重新定义为Nat
?
答案 0 :(得分:2)
是!
{-# 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