Persistent model types in Fay code - haskell

I'm using the Yesod scaffolded site (yesod 1.1.9.2) and spent a few hours yesterday wrapping my head around basic usage of Fay with Yesod. I think I now understand the intended workflow for using Fay to add a chunk of AJAX functionality to a page (I'm going to be a little pedantic here just because someone else might find the step-by-step helpful):
Add a data constructor Example a to SharedTypes.Command.
In the expression case readFromFay Command of ... in Handler.Fay.onCommand, add a case that matches on my new data constructor.
Create a Fay file 'Example.hs' in /fay, patterned after fay/Home.hs. Somewhere in here, use the expression call (Example "foo") $ myFayCallback.
Define a route and handler for the page that will use the Javascript I'm generating. In the handler, use $(fayFile' (ConE 'ScriptR) "Example.hs").
My question: In the current Yesod/Fay architecture, how should I go about sharing my Persistent model types with my Fay code?
Using import Model in a Fay file doesn't work -- when I try to load the page that's using this Fay file, I get an error in the browser (Fay's standard way of alerting me to errors, I guess) indicating that it couldn't find module 'Model' but that it only searched the following directories:
projectroot/cabal-dev//share/fay-0.14.2.0/src
projectroot/cabal-dev/share/fay-base-0.14.2.0/src
projectroot/cabal-dev/share/fay-base-0.14.2.0
projectroot/fay
projectroot/fay-shared
I also tried importing and re-exporting Model in SharedTypes.hs, but that produced the same error.
Is there a way to do this? If not, why not? (I'm a relative noob in both Haskell and Yesod, so the answer to the "why not?" question would be really helpful.)
EDIT:
I just realized that mentioning Persistent in this question's title might be misleading. To be clearer about what I'm trying to do: I just want to be able to represent data in my Fay code using the same datatypes Yesod defines for my models. E.g. if I define a model thusly in config/models...
Foo
bar BarId
textThatCanBeNull Text Maybe
deriving Show
... I want to be able to define an AJAX 'command' that receives and/or returns a value of type Foo and have my Fay code deal in Foos without me having to write any de/serialization code. I understand that I won't be able to use any of Persistent's query functionality directly from my Fay code; I only mentioned Persistent in the title because I mentally associate everything in Model.hs and config/models with Persistent.

This currently is not supported; there are many features leveraged by Persistent which Fay does not support (e.g., Template Haskell). For now, it probably makes sense to have an intermediate data type which is shared by both Fay and Yesod and convert your Persistent data to/from that type.

Related

Where does the resourcesApp come from in Yesod?

The two functions mkYesodData and mkYesodDispatch in the Yesod framework are supposed to separate the handler definition and the dispatch process. Though by some miracle (to me), templates use this interesting function "resourcesApp":
mkYesodDispatch "App" resourcesApp
The only mention of this function I have found in hoogle is in the Hledger package. And it is not a yesod dependency.
In the school of Haskell by this link they give an explanation that resourcesApp is "generated" by mkYesodData, although it still does not work for my side.
https://www.schoolofhaskell.com/school/advanced-haskell/building-a-file-hosting-service-in-yesod/part%202
What is the reason for this?
There's some Template Haskell (TH) going on under the hood in Yesod, and I think this is what's confusing you. Template Haskell can be confusing when searching in documentation because it produces values at compile-time for use at runtime that aren't there before the code is compiled. resourcesApp is just one of these values.
In the code you reference, the author describes that you must have another module (which he calls Foundation) in which you have invoked mkYesodData. Indeed, without this other module, the code in the Dispatch module won't work. Strangely, it's not until (Part 4)[https://www.schoolofhaskell.com/school/advanced-haskell/building-a-file-hosting-service-in-yesod/part%204] that he seems to define the Foundation module, but you can see that there is a line:
mkYesodData "App" $(parseRoutesFile "config/routes")
That may not look like it defines a value called resourcesApp, but sure enough, it does.
In short, you should be able to get your code working by just finishing the entire tutorial and running the code altogether.
In case you're wondeering, a call to mkYesodData takes a String and then literally generates code that defines a value names resources**** where the **** is the string you passed. In this case, that would be a value resourcesApp, but in someone else's Yesod project, it could be resourcesFoo. Furthermore, since this resourcesFoo value isn't concretely in the code, projects that use Yesod typically wouldn't have it show up in their export lists or haddock documentation. It's actually very strange that you found even one hit for resourcesApp on hoogle at all, but upon closer examination, it kind of makes sense: Hledger seems to be some sort of extended interface around yesod, so they pre-generated the TH values so that they would be easily accessible to users.
As another note, TH has some restrictions in its use. For one, you typically need to perform the TH invocations ("splices" as they're typically called) in a separate module than the one you use the generated values. This is probably why the author has you create a separate Foundation module rather than just putting the line mkYesodData ... in the Dispatch module.

How to use helm-semantic-or-imenu for code navigation with type annotated python code

I would like to use the helm-semantic-or-imenu command to navigate components of type annotated Python code, but whatever code analyzer is used to dentify the components doesn't seem to recognize the type annotated python code. Functions with the return type annotation doesn't get recognized at all and functions with annotated arguments show the type instead of the arguments names in the signatures
The main problem I have is that I do not properly understand the components that is involved in making this work (when it does work). Obviously it might help to somehow update the code analyzer, but in which project do I find that? helm? semantic? imenu? or as someone mentioned somewhere else with regards to code analysis python.el? I could really use some help getting started to solve this. If the code analyzer is found in python.el, can I then try to modify and make emacs use a local version preferentially over the installed one?
EDIT:
After making the initial post I finally made a break through in trying to figure out where the components come from. I searched for python*.el in all of the file systemsystem and discovered these:
./usr/share/emacs/26.2/lisp/cedet/semantic/wisent/python.elc
./usr/share/emacs/26.2/lisp/cedet/semantic/wisent/python-wy.elc
I found the source for emacs 26.2 and discovered that indeed it seems python-el is responsible for parsing python files for semantic. It also internally uses the python-wy for recognizing a large portion of the language components. But unfortunately that is where I hit a brick wall. I was hoping to be able to monkey patch the function that recognizes a function definition via an re or something, but semantic actually solves the problem the right way. So python-wy seems to be auto-generated from a formal grammar definition file (in emacs git admin/grammars/python.wy) and figuring out how to modify that it is unfortunately much beyond my abilities.
The semantic python backend doesn't appear to parse type annotations correctly (and there hasn't been much recent development on those libraries as far as I can tell). Since helm-semantic-or-imenu favors semantic when it is active, you can disable semantic altogether for python buffers unless you use its other features (personally I only use it for C/C++).
When the semantic mode-specific libraries are loaded they set imenu-create-default-create-index and imenu-default-goto-function, causing imenu to use semantic instead of python.el's imenu function.
To disable semantic support for your python files you can customize the semantic-new-buffer-setup-functions, only adding entries for modes you want semantic support for, eg. in your semantic hook (or alternatively with the customize UI),
(setq semantic-new-buffer-setup-functions
'((c-mode . semantic-default-c-setup)
(c++-mode . semantic-default-c-setup)
(srecode-template-mode . srecode-template-setup-parser)
(texinfo-mode . semantic-default-texi-setup)
;; etc.
;; (makefile-automake-mode . semantic-default-make-setup)
;; (makefile-mode . semantic-default-make-setup)
;; (makefile-gmake-mode . semantic-default-make-setup)
))

Is there a way to make Haddock render per-argument docs for type class methods?

It turns out that Haddock does not render per-argument docs for type class
methods:
class Foo a where
foo
:: Int -- ^ This string will be ignored by Haddock
-> a
This causes certain issues for users of a library I maintain, because
the methods in my case have quite lengthy signatures. I have always had the descriptions in
the source formatted like that (certainly works for ordinary functions), but
it turns out Haddock does not display them (and does not complain about them
either).
Is there a way to display the per-argument docs with Haddock? Some workaround perhaps?
OK, this was a regression. This thing should work (and worked in version 2.16.1), but stopped (2.17.1 and later).
I have reported this: https://github.com/haskell/haddock/issues/647, should be fixed in version 2.18 (you can see there is a PR for this already).

Config file in haskell

I would like to be able to provide to my Haskell app and config file written in Haskell. The reason why is because I would like the user to be able to provide a few custom functions.
Is it possible to load a haskell file at runtime, even though it might depend on some type provided by the app itself.
At the moment, I have a super main function, and I build a new executable per config file. The file basically, declares some hooks and call super main with them. The problem with that is, at the moment I have to define a new target for each config in my cabal file (I use a sandbox, and I don't want to have to install any library part of my package). I thought using runghc instead but I do I make it works with the sandbox ? I've seen there is a 'plugin' package on hackage but it does't seem to be up to date. What is the common way to deal with this type of problem ?
dyre looks like it fits the bill.

haskell libmagic how to use it?

I'm trying to write a program that will check the file type of a certain file and I found a haskell library that should do the trick.
The problem arises when I try to use it. I have no idea what I have to do, which function to call etc. The library is full of cryptic commands with no examples, no tutorial or a homepage.
Please help.
There is the package's documentation that contains short descriptions of the important functions (which are not that many). For additional information about what the underlying C library does (and therefore also the Haskell library), have a look at libmagic's man page.
The basic usage should look similar to this (untested):
import Magic.Init
import Magic.Operations
main =
do magic <- magicOpen []
loadDefaultMagic magic
magicFile magic "/my/file" >>= print

Resources