I'm passing a record with the following structure to a Template Haskell function:
module Editor.App where
data WithMaybe
data WithoutMaybe
type family TypeSelector a b where
TypeSelector WithMaybe b = Maybe b
TypeSelector WithoutMaybe b = b
data MyRecord a = MyRecord
{ field1 :: TypeSelector a Int
, field2 :: TypeSelector a String
}
$(myTHFunction ''MyRecord)
Inside myTHFunction I'm calling reify and it is correctly giving me the following type-Info:
TyConI
(DataD
[]
Editor.App.MyRecord
[KindedTV a_6989586621679348600 StarT]
Nothing
[RecC Editor.App.MyRecord
[ ( Editor.App.field1
, Bang NoSourceUnpackedness NoSourceStrictness
, AppT (AppT (ConT Editor.App.TypeSelector) (VarT a_6989586621679348600))
(ConT GHC.Types.Int) )
, ( Editor.App.field2
, Bang NoSourceUnpackedness NoSourceStrictness
, AppT (AppT (ConT Editor.App.TypeSelector) (VarT a_6989586621679348600))
(ConT GHC.Base.String) )
]
]
[]
)
However, in my application logic, I cannot proceed with an unapplied KindedTV a_6989586621679348600 StarT. So, my question is:
$(myTHFunction ''(MyRecord SomeSelector)) but that doesn't work.This seems like possibly two questions:
You want to know how to substitute a free type variable in a type.
The best way to do this I know of is to use applySubstitution from the th-abstraction package, which also helpfully includes normalized representations of datatypes across GHC versions so you don’t tether yourself to a single version of Template Haskell.
You want to know how to pass an applied type using TH instead of a single name.
The quoted syntax—i.e. 'ValueName or ''TypeName—quote names, which correspond simply to references to bindings. MyRecord SomeSelector clearly isn’t a name, it’s a type. Therefore, you should use the type quotation syntax instead of the name quotation syntax, which is written [t|MyRecord SomeSelector|]. This quotation will give you a value of type Language.Haskell.TH.Syntax.Type, which is a structured datatype that represents the AST of an arbitrary Haskell type.
As far as I know, there is no function written down in some library that allows you to go directly from a Type with the shape T X ... to the reified list of constructors associated with T, with its argument variables instantiated with types X .... This is, of course, a partial function: [t|forall a. a|] quotes a valid Type, but it is not of the shape T X ..., so you’ll have to handle that failure mode yourself (and hopefully report a useful error message). It can be defined in terms of applySubstitution without too much effort, but you will have to do a bit of groveling through the Type you receive to extract the right information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With