In a very simplified sense, I have something like the following:
type Runtime a = {- More or less a StateT on top of an Either monad -} -- The list of strings in Fn is a bunch of parameter names, the values of -- which are pushed into the state of the runtime before executing the actual -- function expr data Expr = Num Int | Str T.Text | Fn [T.Text] (Runtime Expr) | {- Bunch of other constructors -} eval :: Expr -> Runtime Expr parseExp :: Parser Expr
Now I never used Template Haskell for anything, before I decided that it would be convenient to have a quasi-cycler for my toy language, so I admit that I can skip something obvious.
But in any case, I started to play a little with him, followed some textbooks, etc. and basically discovered that everything but dealing with the Fn constructor was easy.
During my internet gowns on the Internet, I found two common ways that people write an expression:
- Creating your
Expr data Expr is an instance of TH: s Lift and just [| quote |] expression that parsed - Output
Data and Typeable to their Expr equivalent, and then apply dataToExpQ to the same parsing result
In both cases, I ran into complications with Runtime Expr . In the first case, the problem was that I could not figure out how to implement:
instance Lift Expr where lift (Fn ps e) = [| Fn ps ...? |]
(I managed to implement the instance for Data.Text myself, though).
I believe the real problem is that I just don't know TH well enough yet, but so far no number of tutorials or examples have helped me deal with this anywhere.
In the second case, the problem was that for Expr for the Data instance there should also be
instance Data (StateT (...) (Either ...) Expr) where -- Something
Then my question is, is there an easy way to do this? Or maybe I should rethink how the functions of my toy language work?
If the latter, any recommendations on how to get equivalent functionality without running them inside the monad? In the end, this seems like an intuitive solution, as the runtime for the language requires state and error handling (for which I use Either for).