 Hello everyone, my name is Khaled and this will be a really short talk just about my experiences of using the GHC API to solve a thing that was pissing me off a bit. So it started when I was in Brisbane, at the Brisbane Functional Programmes Group back in about 2013 and Sam Roberts did a talk about his experiences of working at Standard Chartered, where I now work. And he said that people who were learning Haskell for the first time, the ones who were using the visual environment seemed to go better than the people who just thrashed away with the more humax or other sort of horrible things. And so I wondered if there was anything I could add to my sort of way that I developed because I'm extremely old school and I have an ex-term and I don't use any plugins. I thought maybe I should add something and be a bit more modern about what I'm doing. So Haskell's got a pretty good time system that does a lot for you, and I thought you should be able to leverage that in the process of doing the coding. So programming is done and my brain is small, so those things kind of come together. And I thought maybe I can write some kind of in-plug in to just help a little bit, you know, make the dailies and the tasks a bit easier. I think at the time I was playing with Yesog as well, and there were just millions of functions and I've all got weird little names. So this is one example that you might be writing some code. I was like, you're reading someone else's code and you see a thing that says, map him on the switch and you think, what's that? Can't be too hard to look this up. If you go to Hoogle, which is on the web, it'll tell you that it's from Prelude or maybe Control.monad, or maybe it's from data.foldable, and you might start wondering what's the difference between that. And at the time, Hoogle didn't tell me about map him on the switch or from data.conure on the list, which was the thing that I was actually using at the time, because obviously Hoogle doesn't know what's on your computer. And so I thought maybe the simplest thing you could do is use GHC Mod, which is fantastic, just to have a look at the info thing and then surely you could just look up the documentation. How hard could it be, right? And it turns out it's a complete mess. So something like map him is in Control.monad, and I think that matches correctly for this. But then if you ask for some other symbols like map, it'll tell you ghc.face, and there is no actual Google, I mean, package URL that matches ghc.face. There's no package called ghc.face. So straight off the bat, I've realized that things are not going to work properly. So in the first example, you try to send yourself to that URL, which goes Control.monad, and the other one, the other thing is that you don't know which version of anything you have in. So depending on which version of ghc, maybe you've got base 4.6, or maybe you've got base 4.7, which relates to ghc.7.something. So as a user, you're just not going to have this kind of stuff in your head. So then this is just another sort of example that sometimes people tell you, the intro command will tell you things are not exactly right either. Like if you ask about head, it tells you that it's defined in ghc.list, but that's not right because it's not really correct. It's actually from data.list. If you want to go to package, and look at how the documentation will be data.list. So I thought maybe this would be a good opportunity to use the ghc API and sort of query the source code a bit, and maybe the compiler can give me a little bit of information about where stuff is. And so you can quite easily, using the API, ask for a few things like tell me the imports to the hidden module, and it will tell you stuff like you have import data.list. You can ask for the names in there. So if you just have a string like hgad, you need to map that to something else that corresponds to something in the ghc syntax tree. And you want to find out where it's imported from, not where it's defined, because where it's defined could be ghc.list, where it's imported from, the sort of any other stuff. And then you've got to get a nice URL. When I wrote this, I was spending most of my time working in cafes, because I was a stay-at-home dad. So I had a little 3G data, and I always wanted to have a locally built documentation, not something on a hack addition. So, basically by reading the ghc mod source code, I found that it's not too hard to sort of load up a module. You do everything in a ghc monad, so you have to do a run ghc at the start. And then you can just set a bunch of things like dynamic, the session flags are things like where your compile sandbox is, and other kind of finicky things. So you initialize stuff, and then you tell it, guess this target, which is this file that you have, and try to load it up. And if you get these things slightly wrong, you get ghc connects, which is really nice. And yeah, so the API gives you stuff that will get the summary of a module. It will parse it for you, type check it, and then de-sugar it. And that's all you really need to do to start poking into the inside of your module. And there's ways to do this without fully compiling the whole thing, so that it goes a little bit quicker. And I found just by ruining all of the ghc API documentation, which is a lot of it, but it doesn't tell you what anything is, like it just gives you the function signatures. I found this thing called mod guts, which is the guts. And the guts has everything, like everything that gets carried along as ghc compiles something. And inside the guts, I found the thing called the global reader environment. And that thing is basically full of the names of everything that ghc has found. And you can't print anything sort of by default. You have to use a show estock, which uses the dflags, because apparently that context changes how you might use stuff. But once you do that, you get millions of things like this. And I thought, oh, this is what we actually want. So this IHZ is some kind of internal thing, which was telling me that our map, which is defined in ghc.base, is imported from the prelude. And that's exactly what you need, that you want to tell the user, map there comes from the prelude, and then go to the right documentation. And basically, we try to get from MAP at that point in the text to that entry in the guts of ghc, and then to the URL down the bottom. And so in slightly more detail, and you don't have to fully get all this, but you partially compile the things so you can get a bunch of names, you get fully qualified names like ghc.list.it, and then you have to kind of match it with the name you actually hope might fit. And there's a little bit of weirdness with that, because apparently the order that you load the modules can affect which names kind of exist in the space. You sort of work out where it really came from. This will go away in the next version, because we don't really need to use ghc package, but basically you want to be told the package thing that it's in, like I don't know why it's possible 2010, and then one of those URLs. And so for this example, this is on my file system, because when I write the slides, I was using ghc 7.8.4. We have a question. Yeah, sir. So how much of the combination by finding the name around the case in your example, you had the browser type checker, and then just running up the rename should be as far as... As far as I could tell, to get the mod guards. Yeah, but you don't really need the mod guards. You just need to read around by reading, right? Yeah, so where's the... Yeah, but where can you get... So here, that's coming out of the guards. Yeah, so I think... Well, I could be wrong, but I think I tried doing less of this, and I didn't get the names that I wanted. But I could be wrong, because this is like... Yeah, so I think what you should try and see is instead of doing the full type check module, if you manually run only the re-name, then you run the RMO and then whatever you get out of it, you should have this reader environment. Okay. Because yeah, that type... Well, okay. So you can definitely... You can definitely see the gap between the people I've done and the people I've been to in my own life, and the tour has gone. So the re-name... I used re-name, and now I have a completely different... And I've been able to do that, but it takes a lot more elbow reading than doing the full type check. But even then, even if you decide to do the full type check, even then, shouldn't you need to do de-sugar it? Yeah, I don't think so. I think you should be pushing the... I was not aware that you... I would also assume that you don't need to de-sugar it, but I was not aware you can do the re-name type check. Anyway, show me afterwards where it is, and I'll happily remove the code. Well, I mean, you will be adding more to it, because it's not as straightforward as this, but you will be running less on the compiler at night, and your code will work with non-well-dived... It doesn't have other question I had, except with this current setup, this only works if the module that you are writing is a full type check, which is another problem. Yeah, which is a huge problem, I'd say. Submit a pull request. See? Submit a pull request. So, anyway, that's my feeling of the code at the moment, that we're sort of looking for something. I think that the GHC API should be able to hand this information to you very clearly, but that's kind of how it feels. So, in terms of using it, I've written a bin plug-in for this name, this other guy wrote an Emacs plug-in, so everyone can use it, and that's an example. You can just ask it to print the URL at the bottom or you can make it load it up in your browser, so there I was looking at something from .dl.length. So it handles all those sort of weird things, like if you import qualified .dl. and then ask what dl.length is and sort of go back and work out what that was. That was just, so the word just came from the prelude. If you import, so if you're using a qualified name, it's kind of the same thing, like, saved. So in this case, I didn't have the locally built documentation for some reason, so it's sending me to the equivalent URL on package.casper.lib, so it does its best to go local and then go up. That was, I think that's a bit of the code itself, so it's like poking into the project. I mean, it's just looking stuff up. Shadowing. Shadowing. Yeah. Yeah, it doesn't do very well for locally defined stuff, so if you use it in your own code, so where did this thing that I made come from? No, but I mean, if you find something called head, do you think that you are looking for documentation for data that we still have? Probably, yeah. So it just doesn't do local stuff. It's more for using a big library and it's sort of crazy stuff. You don't know where anything is. Yeah, so I've found it useful myself. I've been doing development, someone wrote an Emacs, David Christensen wrote an Emacs plugin, and there's weird corner cases with the module system that you can just have. It does, I feel like the module system kind of grew organically and people can think about how things were going to go. And basically, GHC module is very useful. It does a lot of the dull work of finding where your sandbox is or what the package names are and all that sort of stuff. Yeah. So that's basically it. It's on GitHub and, yeah, or a package. It's pretty exciting to use. So that's an example. You think, where does default runner come from? Can you tell me? Tell me where it comes from. There it is. So that's good. Because at the moment, there's no way to get there. Because every name in Haskell is like some little simple word like default or something. Where does it come from? Yeah. So that's pretty much it. The question is, tool requests? I wonder if you could put a hole at the corner and then somehow get everything which is in school right there and then I get to read the environments for some such in that particular place and then look up things there and then gradually they compare but I'm not sure if you can do that I'm just saying that this could be an annual attack or something like that. I also, the other day I found a function that seems to talk about does a symbol get exported from a module which I just never saw. So there's probably other things around the place that might be good. The GHC API could keep this kind of stuff if they connected a bit better the documentation to it. Like this isn't rocket science really we're just trying to find the documentation. If anyone does this in a different way I'd like to. How do people find things? Is everyone just psychic and knows where everything is? No one's just that good. They've memorized all the documentation.