TypeLit from generic Integer expression

偶尔善良 提交于 2019-12-11 10:47:57

问题


The only way I know to construct a Nat is to use -XDataKinds with promoted integers, i.e., type MyInt = 10 :: Nat.

Instead, I'd like to have a function

foo :: Integer -> Integer

that I can index with a reflected Nat, and then reify the result. To demonstrate what I mean, assume some function mkNat :: Integer -> Q Type. I want to write

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

(In my example, foo is fast enough that it can be computed at compile time without prohibitive overhead.) Having this capability saves me the multi-step process of running foo in a separate GHCi session, then copying the decimal representation of the result into a source file, and then compiling the code I really wanted.

Of course the only missing component is mkNat. If I write my own custom data type, the equivalent of mkNat is easy to write. But I'd really like to use the built-in TypeLits. Is there some TemplateHaskell (or singletons, or some other magic) that would allow me to reify an arbitrary Integer expression to a Nat?


回答1:


Yes!

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

module Main where

import Data.Proxy
import GHC.TypeLits
import Splices

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

And then:

module Splices where

import Language.Haskell.TH

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


来源:https://stackoverflow.com/questions/36062614/typelit-from-generic-integer-expression

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!