来自通用整数表达式的 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
我知道构造 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