
I'm implementing Template Haskell support for injective type families and I'm struggling to understand DsMeta module. It seems that all functions in that module delegate their calls to functions in Language.Haskell.TH.Lib via wired-in names and the `DsMeta.rep2` function. I'm puzzled by this design and I'd appreciate if someone could explain why things are done this way. Take this function example: repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr) repPlainTV (MkC nm) = rep2 plainTVName [nm] where `plainTvName` is a name of `Language.Haskell.TH.Lib.plainTV`: plainTV :: Name -> TyVarBndr plainTV = PlainTV Why not implement repPlainTV like this: ? repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr) repPlainTV (MkC nm) = return $ MkC (TH.PlainTV nm) Janek

On Dec 17, 2014, at 12:29 PM, Jan Stolarek
Why not implement repPlainTV like this: ?
repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr) repPlainTV (MkC nm) = return $ MkC (TH.PlainTV nm)
In short, that's ill typed. We have
newtype Core a = MkC CoreExpr
The idea behind this type is that its (phantom) type parameter tracks the type of the expression stored within. Of course, the thing within is always just a core expression. TH.PlainTV takes a TH.Name and produces a TH.TyVarBndr. But, nm is a CoreExpr and MkC is expecting a CoreExpr, so your suggestion wouldn't type check. The higher-level answer is that you're mixing levels. The goal in DsMeta is *not* to create the TH AST. It's to create *core expressions* that create the TH AST. Does this help? Richard

Thanks. That helps but I still don't understand why the calls are delegated to template-haskell library. Couldn't all of this be done locally? Janek Dnia środa, 17 grudnia 2014, Richard Eisenberg napisał:
On Dec 17, 2014, at 12:29 PM, Jan Stolarek
wrote: Why not implement repPlainTV like this: ?
repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr) repPlainTV (MkC nm) = return $ MkC (TH.PlainTV nm)
In short, that's ill typed. We have
newtype Core a = MkC CoreExpr
The idea behind this type is that its (phantom) type parameter tracks the type of the expression stored within. Of course, the thing within is always just a core expression. TH.PlainTV takes a TH.Name and produces a TH.TyVarBndr. But, nm is a CoreExpr and MkC is expecting a CoreExpr, so your suggestion wouldn't type check.
The higher-level answer is that you're mixing levels. The goal in DsMeta is *not* to create the TH AST. It's to create *core expressions* that create the TH AST.
Does this help?
Richard

But you need an expression that, say, produces a PlainTV. Where are you going to find an expression that does this without using the template-haskell library?
On Dec 17, 2014, at 2:33 PM, Jan Stolarek
Thanks. That helps but I still don't understand why the calls are delegated to template-haskell library. Couldn't all of this be done locally?
Janek
Dnia środa, 17 grudnia 2014, Richard Eisenberg napisał:
On Dec 17, 2014, at 12:29 PM, Jan Stolarek
wrote: Why not implement repPlainTV like this: ?
repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr) repPlainTV (MkC nm) = return $ MkC (TH.PlainTV nm)
In short, that's ill typed. We have
newtype Core a = MkC CoreExpr
The idea behind this type is that its (phantom) type parameter tracks the type of the expression stored within. Of course, the thing within is always just a core expression. TH.PlainTV takes a TH.Name and produces a TH.TyVarBndr. But, nm is a CoreExpr and MkC is expecting a CoreExpr, so your suggestion wouldn't type check.
The higher-level answer is that you're mixing levels. The goal in DsMeta is *not* to create the TH AST. It's to create *core expressions* that create the TH AST.
Does this help?
Richard

| Thanks. That helps but I still don't understand why the calls are
| delegated to template-haskell library. Couldn't all of this be done
| locally?
No. If you have
f :: Int -> Q Exp
then f is a function that, when run, produces a data structure that is the syntax tree (in the data type of Language.Haskell.TH) of some expression.
Later, in some other module entirely, you may call f, thus
foo = $(f 5)
Now GHC dynamically links the module that defines f, executes f's code, which returns a syntax tree (in the data type of Language.Haskell.TH). This is converted to HsSyn and replaces the $(f 5).
So the code for f must be code that, when executed, produces a data structure. The business of DsMeta is to produce such code.
If, once you grok this, you'd like to add a page to the GHC Commentary, to explain it, that would be great. It does take a while to get your head around.
Simon
| -----Original Message-----
| From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Jan
| Stolarek
| Sent: 17 December 2014 19:34
| To: Richard Eisenberg
| Cc: ghc-devs@haskell.org
| Subject: Re: Understanding DsMeta module
|
| Thanks. That helps but I still don't understand why the calls are
| delegated to template-haskell library. Couldn't all of this be done
| locally?
|
| Janek
|
| Dnia środa, 17 grudnia 2014, Richard Eisenberg napisał:
| > On Dec 17, 2014, at 12:29 PM, Jan Stolarek
participants (3)
-
Jan Stolarek
-
Richard Eisenberg
-
Simon Peyton Jones