来自通用整数表达式

时间:2016-03-17 13:54:10

标签: haskell ghc

我知道构建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

1 个答案:

答案 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