I'm currently working on a library that allows the user to specify a list of command specifications as follows:
data CommandDef = forall (as :: [*]). Typeable as => CommandDef {
argTypes :: Proxy as,
commandName :: String,
commandStrings :: [String],
parsers :: HList (FMap CommandParser as),
description :: Maybe String
}
This list of command specifications can then be passed into a template haskell function genCommands :: [CommandDef] -> Q [Dec]
to generate a Command
data type representing the different types of commands that the user has specified, together with a function parseCommands :: String -> Maybe Command
, where argTypes
specifies the types of the command's arguments to be parsed, and parsers
is an HList of the relevant parsers for the given argTypes
.
The issue is, I need to somehow get a Type
(from Language.Haskell.TH) for each of the argTypes
in a CommandDef
in order to properly generate the Command
type with Template Haskell -- while still keeping the type safety of making sure all of the parsers
are of the appropriate type. (The idea is, if commandName = "CommandName
and argTypes = Proxy @'[ArgType1, ArgType2]
, a constructor of form CommandName ArgType1 ArgType2
will be generated in the Command
type.)
So, really, in an ideal world, what I would like is a function Proxy as -> Q [Type]
, or something similar, but I'm not sure if this is possible to do in Template Haskell.
Is there such a thing? Or is there any way my approach could be modified in order to accomplish all of the same goals with Template Haskell?
I have considered adding a redundant field argTypesTH :: [Name]
which contains all of the names of the types in argTypes
, but I'm not even sure how this could work, because I can't seem to find a template haskell function which takes a type name, and returns the needed Type
that needs to be specified for the constructors of my Command
type. (There is reifyType
, but I'm not sure if that can do what I want, as that takes the name of a value and returns a type)