<div dir="ltr">I considered an expression-within-an-expression but thought a stage-restriction would break it. Maybe not! Let me go test it!</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 21 Aug 2019 at 17:31, Michael Sloan <<a href="mailto:mgsloan@gmail.com">mgsloan@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">One potential solution here is to have checkGrammar_take2 return an<br>
expression which returns an expression.  I haven't tried compiling<br>
this, but something roughly like:<br>
<br>
checkGrammar_2 name = [| if valueFine $(varE name) then varE name else<br>
error "value isn't fine" |]<br>
<br>
Then it'd be used like $($(checkGrammar_2 'thename)).  The th-orphans<br>
package can also be useful for this because it provides Lift instances<br>
for the TH AST.<br>
<br>
-Michael<br>
<br>
On Tue, Aug 20, 2019 at 10:36 AM Christopher Done <<a href="mailto:chrisdone@gmail.com" target="_blank">chrisdone@gmail.com</a>> wrote:<br>
><br>
> Hi all,<br>
><br>
> Do we have already a syntax for ‘foo that also contains the typed value like TExp?<br>
><br>
> I have e.g. an AST that I want to do more static checks on it that aren’t as convenient to do in the type system. Here’s an example:<br>
><br>
> -- | Check the grammar spec to produce a grammar.<br>
> checkGrammar :: (SchemaName, [(SchemaName, Schema)]) -> Q Exp<br>
> checkGrammar (toplevel, rules) =<br>
>   if M.size rulesMap /= length rules<br>
>     then error "Duplicate rule names in grammar."<br>
>     else lift (Grammar {grammarToplevel = toplevel, grammarRules = rulesMap})<br>
>   where<br>
>     rulesMap = M.fromList rules<br>
><br>
> -- | Grammar for Haskell.<br>
> grammar :: Grammar<br>
> grammar = $(checkGrammar $ runDefine $ mdo<br>
>   -- General expression<br>
>   expression       <- rule "Expression" (ChoiceSchema [variable, constructor, parentheses<br>
>                                                       ,tuple, let', application, string])<br>
>   application      <- rule "Application" (CompositeSchema [expression, expression])<br>
>   parentheses      <- rule "Parentheses" (CompositeSchema [openParenSchema, expression, closeParenSchema])<br>
><br>
> ...<br>
>  pure expression)<br>
><br>
> Here I do a trivial check for duplicates. After I’ve checked the<br>
> expression at compile-time, I Lift it so that it can be used at<br>
> runtime. That’s pretty good. But some types like (a -> b) don’t Lift. So<br>
> an alternative would be:<br>
><br>
> grammar = $(checkGrammar_take2 thename 'thename)<br>
><br>
> In which checkGrammar_take2 would:<br>
><br>
> Use thename at compile-time for a check.<br>
> If the check passes, then return (VarE thename)<br>
><br>
> E.g.<br>
><br>
> checkGrammar_take2 value name = if valueFine value then varE name else<br>
> error "value isn't fine"<br>
><br>
> That’s actually quite a good solution because it avoids a lift, and I<br>
> didn’t transform the AST. It’s also more efficient than lifting.<br>
><br>
> But there’s no checked relationship between thename and ‘thename.<br>
> checkGrammar_take2 has no way of knowing that they refer to the same<br>
> thing. See?<br>
><br>
> Hence, if I could get e.g. `thename to produce both the value and a<br>
> name for the value, that would be cool. My gist doesn’t go this<br>
> far. It might look like this:<br>
><br>
> checkGrammar_take2 namedValue = if valueFine (getValue namedValue) then getExp namedValue else error "value isn't fine"<br>
><br>
> and call it like:<br>
><br>
> mygrammar = checkGrammar_take2 `thename<br>
><br>
> So the semantics would be roughly similar to<br>
><br>
> [|| thename ||] :: TExp a<br>
><br>
> but you’d get<br>
><br>
> `thename :: Named a<br>
><br>
> where<br>
><br>
> data Named a = { namedThing :: a, nameOfThing :: Name }<br>
><br>
> I feel like the more DSLs I design, the more I’d like something like this to perform my static checks.<br>
><br>
> Cheers,<br>
><br>
> Chris<br>
><br>
> _______________________________________________<br>
> Haskell-Cafe mailing list<br>
> To (un)subscribe, modify options or view archives go to:<br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
> Only members subscribed via the mailman list are allowed to post.<br>
</blockquote></div>