WEBVTT captioned by anush 00:00.000 --> 00:03.499 Today, I will talk about Haskell code exploration for Emacs. 00:03.500 --> 00:06.499 What is Haskell? It is a purely functional language. 00:06.500 --> 00:09.499 For example, every value in Haskell is immutable. 00:09.500 --> 00:12.999 And it is the main compiler of Haskell, GHC. 00:13.000 --> 00:15.999 It provides API for the whole compilation pipeline. 00:16.000 --> 00:00:18.324 For example, the tools mentioned in this talk, 00:00:18.424 --> 00:00:19.999 including hcel and haddorg, 00:20.000 --> 00:24.499 they use, they heavily utilize the GHC front-end API 00:24.500 --> 00:00:26.644 for parsing and understanding 00:00:26.744 --> 00:00:29.499 the identifiers in Haskell source files. 00:29.500 --> 00:00:31.444 Roughly speaking, 00:00:31.544 --> 00:00:34.564 a Haskell program consists of several parts. 00:00:34.664 --> 00:00:36.964 it begins with some front matters, including, 00:00:37.064 --> 00:00:39.924 for example, language extensions, 00:00:40.024 --> 00:00:43.964 which are optional language features one might want to use 00:00:44.064 --> 00:00:48.364 for convenience. 00:00:48.464 --> 00:00:52.499 The front matters also contain module exports. 00:52.500 --> 00:00:55.684 So for example, here we define, 00:00:55.784 --> 00:00:57.999 we declare module F2Md.Config 00:58.000 --> 00:01:00.884 for this Haskell source file, 00:01:00.984 --> 00:01:02.999 which exports these four identifiers 01:03.000 --> 01:07.499 that other source files can use when importing F2Md.Config. 01:07.500 --> 00:01:10.684 And the next will be 00:01:10.784 --> 00:01:13.999 a block of imports so that we can use libraries 01:14.000 --> 01:16.999 and identifiers in these libraries. 01:17.000 --> 00:01:21.644 The bulk of a Haskell source file normally is 00:01:21.744 --> 00:01:22.999 a list of declarations, 01:23.000 --> 01:25.999 including values, types, and instances, and so on. 01:26.000 --> 00:01:29.084 The difference between a value and a type is that 00:01:29.184 --> 00:01:30.499 the type of a value is a type, 01:30.500 --> 00:01:33.964 and the type of a type is a kind. 00:01:34.064 --> 00:01:38.484 For example, here's a small block of Haskell source code. 00:01:38.584 --> 00:01:41.404 We define Range type 00:01:41.504 --> 00:01:44.999 from a lower-end integer to a higher-end integer. 01:45.000 --> 00:01:51.364 We also declare a value r of the type Range, 00:01:51.464 --> 00:01:53.999 which is Range from 2 to 7, 01:54.000 --> 00:02:01.004 because in Haskell, we like to-- 00:02:01.104 --> 00:02:03.999 by default, functions can be curried, 02:04.000 --> 00:02:09.804 which basically means, by default, we want to utilize 00:02:09.904 --> 00:02:11.999 the partial application of functions. 00:02:12.000 --> 00:02:17.284 We don't require parens surrounding arguments 00:02:17.384 --> 00:02:19.364 when invoking a function. 00:02:19.464 --> 00:02:22.724 That makes it possible, if you want, 00:02:22.725 --> 00:02:24.999 to write Haskell like Lisp 02:25.000 --> 02:27.999 by adding a bit of redundant parens. 02:28.000 --> 00:02:30.044 So for example, 00:02:30.144 --> 00:02:33.684 here are two blocks of code, one Lisp, one Haskell, 00:02:33.784 --> 00:02:35.999 and they look quite similar to each other. 02:36.000 --> 02:37.999 What is a code explorer? 02:38.000 --> 00:02:39.444 A code explorer is a tool 00:02:39.544 --> 00:02:42.624 to browse its code base to its code comprehension. 00:02:42.724 --> 00:02:45.324 Code explorer commonly comes with 00:02:45.424 --> 00:02:46.999 several functionalities or features, 02:47.000 --> 00:02:49.244 including a cross-referencer, 00:02:49.344 --> 00:02:52.999 which allows going to definitions of an identifier at points 02:53.000 --> 00:02:56.444 or looking up references of an identifier, 00:02:56.544 --> 00:02:57.999 like where it is used. 02:58.000 --> 03:03.999 So the example in Emacs would be xref. 03:04.000 --> 00:03:07.604 Code explorer also would be able to show you 00:03:07.704 --> 00:03:09.999 documentation and signatures of identifiers at points. 03:10.000 --> 00:03:13.884 In Emacs, that would be eldoc. 00:03:13.984 --> 00:03:16.999 It also commonly allows you to search for identifiers. 03:17.000 --> 00:03:19.884 Something like that in Emacs 00:03:19.984 --> 00:03:21.999 could be describe-function and find-function. 03:22.000 --> 00:03:24.684 Code explorer is normally 00:03:24.784 --> 00:03:27.364 quite often implemented in two parts, 00:03:27.464 --> 00:03:27.999 the indexer and the server, 03:28.000 --> 00:03:32.484 where the indexer parses the source code files, 00:03:32.584 --> 00:03:33.999 indexes the identifiers, 03:34.000 --> 00:03:36.284 and stores the information of identifiers 00:03:36.384 --> 00:03:37.999 like the definition, size, and the currencies, 03:38.000 --> 03:41.999 either in databases or in files. 03:42.000 --> 00:03:44.444 The other part is the server, 00:03:44.544 --> 00:03:48.999 which uses the database created by the indexer 03:49.000 --> 00:03:53.004 to serve the information of the identifier. 00:03:53.104 --> 00:03:57.004 Before I present my solution to code exploring, 00:03:57.104 --> 00:04:00.999 some description of prior art is in order. 04:01.000 --> 00:04:05.284 There are several tools that you can use 00:04:05.384 --> 00:04:07.999 to aid code exploration, 04:08.000 --> 00:04:13.444 including tech-based tools like hasktags and hs-tags. 00:04:13.544 --> 00:04:15.484 The limitation with these tools 00:04:15.584 --> 00:04:17.999 is they are focused on the current projects only 04:18.000 --> 00:04:19.604 and do not work 00:04:19.704 --> 00:04:25.999 for cross-packaging reference and definition. 04:26.000 --> 00:04:31.044 Another problem with the tag-based tools is 00:04:31.045 --> 00:04:34.684 they might not handle symbols with the same name properly. 00:04:34.784 --> 00:04:35.999 Sometimes they get confused, 04:36.000 --> 00:04:43.324 and they ask you to choose which definition, 00:04:43.424 --> 00:04:45.924 what is the correct definition site, 00:04:46.024 --> 00:04:49.244 even though the occurrence of the symbol 00:04:49.344 --> 00:04:54.999 or the symbol at point has only one definition ambiguously. 04:55.000 --> 04:57.999 Another tool is the haskell-mode. 04:58.000 --> 00:05:02.684 It has some limited support for eldoc 00:05:02.784 --> 00:05:06.604 by displaying the signature of an identifier at points, 00:05:06.704 --> 00:05:11.764 but the identifier has to be something 00:05:11.864 --> 00:05:14.999 that is commonly known or sort of built-in 05:15.000 --> 05:17.999 or come from the base library of Haskell. 05:18.000 --> 00:05:20.244 So for example, 00:05:20.344 --> 00:05:24.244 it works for common functions like head and tail. 00:05:24.344 --> 00:05:26.999 And you can see that the signature is displayed here. 05:27.000 --> 00:05:29.564 However, it does not work for, 00:05:29.664 --> 00:05:31.804 let's say, IO. IO is a type. 00:05:31.904 --> 00:05:32.999 Maybe that's the reason. 05:33.000 --> 00:05:37.324 Let's find another function 00:05:37.424 --> 00:05:39.999 that's not from the base library. 05:40.000 --> 05:41.999 toJSON is from the Aeson library, 05:42.000 --> 05:46.999 so no signature is displayed here. 05:47.000 --> 00:05:51.164 It also provides 00:05:51.264 --> 00:05:53.324 some sort of goto-declaration functionality 00:05:53.424 --> 00:05:56.324 to jump to any declaration in a file. 00:05:56.424 --> 00:06:00.564 To do that, one has to first run haskell-decl-scan-mode 00:06:00.664 --> 00:06:02.999 to enter this minor mode. 06:03.000 --> 00:06:08.044 Then we can run imenu to go to any definition, 00:06:08.144 --> 00:06:10.999 to go to any declaration, like getHomeR. 06:11.000 --> 00:06:13.724 Apparently, after running that, 00:06:13.824 --> 00:06:15.999 we are able to go to definition. 06:16.000 --> 06:18.999 So for example, let's see, 06:19.000 --> 06:21.999 we want to find definition of getCityJR. 06:22.000 --> 00:06:25.524 And indeed, it works 00:06:25.624 --> 00:06:28.524 if it's within the same source file, of course. 00:06:28.624 --> 00:06:31.999 It still does not work for cross-packaging identifiers. 06:32.000 --> 00:06:36.924 So HandlerFor is probably an identifier from servant. 00:06:37.024 --> 00:06:39.999 Or no, not necessarily servant. Maybe WAI. 06:40.000 --> 00:06:43.404 Anyway, it's another library. 00:06:43.504 --> 00:06:50.404 And how about find-references? 00:06:50.504 --> 00:07:01.124 find-references also works somehow for this file. 00:07:01.224 --> 00:07:06.684 How about WidgetFor? 00:07:06.784 --> 00:07:13.644 It works for WidgetFor too. 00:07:13.744 --> 00:07:17.999 It has some support for goto-definition and find-references. 07:18.000 --> 07:25.999 But as usual, it does not support such things cross-package. 07:26.000 --> 00:07:27.364 And finally, we have 00:07:27.365 --> 00:07:30.999 the Sledgehammer HLS Haskell language server. 07:31.000 --> 07:32.999 It can be used with EGLOT. 07:33.000 --> 00:07:40.804 But the problem with HLS, HLS has many many features 00:07:40.904 --> 00:07:42.844 because it is a language server, 00:07:42.944 --> 00:07:50.999 like renaming, like eldoc for standard libraries, and so on. 07:51.000 --> 07:56.999 But the problem with HLS is, one, that it is very, very slow. 07:57.000 --> 07:59.999 And I wouldn't use it with my laptop. 08:00.000 --> 08:04.999 And two, it also does not support cross-package referencing. 08:05.000 --> 08:07.999 In fact, there's an outstanding GitHub issue about this. 08:08.000 --> 00:08:12.964 So cross-package referencing and goto-definition 00:08:13.064 --> 00:08:17.164 is sort of a common shortfall, 00:08:17.264 --> 00:08:20.999 a common problem for these existing Haskell code explorers. 08:21.000 --> 08:22.999 Then finally, we also have hoogle and hackage. 08:23.000 --> 00:08:28.284 Hoogle is a search engine for Haskell identifiers, 00:08:28.384 --> 00:08:30.644 and the results link to Hackage, 00:08:30.744 --> 00:08:33.604 which is the Haskell documentation website 00:08:33.704 --> 00:08:34.999 for all Haskell libraries. 08:35.000 --> 00:08:40.004 Haskell Hackage has functionality 00:08:40.104 --> 00:08:44.999 where you can jump to the source code file rendered in HTML, 08:45.000 --> 00:08:49.444 and you can click on the identifiers there 00:08:49.544 --> 00:08:51.524 to jump to definitions, 00:08:51.624 --> 00:08:54.044 but it does not support find references, 00:08:54.144 --> 00:08:58.999 and it is rather basic. 08:59.000 --> 00:09:01.644 Then I learned about haskell-code-explorer, 00:09:01.744 --> 00:09:04.999 which is a fully-fledged Haskell code explorer. 09:05.000 --> 00:09:07.724 It is written by someone else. 00:09:07.824 --> 00:09:09.164 It is a web application 00:09:09.264 --> 00:09:11.999 for exploring Haskell package codebases. 09:12.000 --> 00:09:16.244 The official reference instance for haskell-code-explorer 00:09:16.344 --> 00:09:18.999 is available at this URL, which I will demo soon. 09:19.000 --> 09:24.999 What I did with these packages... I ported it to GHC 9.2. 09:25.000 --> 00:09:29.044 I renamed it to hcel because I want to focus on Emacs clients 00:09:29.144 --> 00:09:30.999 rather than JavaScript clients, which I will explain later. 09:31.000 --> 09:36.999 And I also wrote an Emacs client package, of course. 09:37.000 --> 00:09:41.404 This is what haskell-code-explorer looks like. 00:09:41.504 --> 00:09:46.924 On the homepage, it is a list of indexed packages 00:09:47.024 --> 00:09:50.044 indexed by the indexer. 00:09:50.144 --> 00:09:53.844 One can filter it by the package name 00:09:53.944 --> 00:10:04.999 or look for identifiers directly across all packages. 10:05.000 --> 00:10:09.884 Let's have a look at base. There are three versions. 00:10:09.984 --> 00:10:14.999 Let's have a look at the latest version, 4.12.0.0. 10:15.000 --> 00:10:18.964 Once entering the package view, 00:10:19.064 --> 00:10:24.444 you are shown a list of all modules by their path, 00:10:24.544 --> 00:10:28.999 as well as a tree of these module files. 10:29.000 --> 00:10:32.524 You can filter by module name or file name, 00:10:32.624 --> 00:10:34.324 or you can search for identifier within the same package 00:10:34.424 --> 00:10:35.999 or in all packages. 10:36.000 --> 00:10:43.204 Let's say we want to learn about Control.Monad. 00:10:43.304 --> 00:10:46.884 Now we are in the module view. 00:10:46.984 --> 00:10:49.804 The source file is presented to you, 00:10:49.904 --> 00:10:54.999 and it has links to identifiers. 10:55.000 --> 00:11:01.804 When you hover over them, the documentation shows up, 00:11:01.904 --> 00:11:04.999 including the signature where it is defined. 11:05.000 --> 00:11:10.244 You can go to its definition or find references. 00:11:10.344 --> 00:11:20.164 Let's say we want to go to the definition of Monad. 00:11:20.264 --> 00:11:25.484 It jumps to the definition site of the monad type class. 00:11:25.584 --> 00:11:28.004 If we click at the definition site, 00:11:28.104 --> 00:11:32.124 it brings up a list of references. 00:11:32.224 --> 00:11:33.644 On the left, you can choose 00:11:33.744 --> 00:11:38.999 which package you want to find references of monad in. 11:39.000 --> 11:46.999 Let's look at the random one, avwx. 11:47.000 --> 00:11:54.044 Here is a list of results where Monad is used in avwx. 00:11:54.144 --> 00:11:57.764 This is a module path. 00:11:57.864 --> 00:12:06.324 One can go to any of these results. 00:12:06.424 --> 00:12:07.844 We can search for things in all packages 00:12:07.944 --> 00:12:09.484 or in the current package. 00:12:09.584 --> 00:12:12.999 Let’s say I want to search for "Read" 12:13.000 --> 00:12:19.244 I think this is the "Read" that is commonly used in Haskell, 00:12:19.344 --> 00:12:24.999 the read type class for parsing strings into values. 12:25.000 --> 00:12:31.004 I think that is more or less it. 00:12:31.104 --> 00:12:34.524 That is the Haskell Code Explorer web application 00:12:34.624 --> 00:12:38.204 in all its glory. 00:12:38.304 --> 00:12:40.884 Let's go back to the slides. 00:12:40.984 --> 00:12:43.364 That was the web application, 00:12:43.464 --> 00:12:46.444 which is basically a JavaScript client 00:12:46.544 --> 00:12:48.644 that talks to the server 00:12:48.744 --> 00:12:50.964 by sending requests and receiving 00:12:51.064 --> 00:12:54.999 and parsing the JSON results or JSON responses. 12:55.000 --> 00:13:02.404 Initially, I was interested in hacking the web client. 00:13:02.504 --> 00:13:04.999 It uses the ember.js web framework. 13:05.000 --> 00:13:09.844 The first thing to do was to npm install ember-cli. 00:13:09.944 --> 00:13:16.124 It gives me 12 vulnerabilities, 00:13:16.224 --> 00:13:18.999 4 low, 2 moderate, 3 high, 3 critical. 13:19.000 --> 00:13:26.084 I don't know how often it is the case 00:13:26.184 --> 00:13:32.964 when we don't really care about these nasty vulnerabilities 00:13:33.064 --> 00:13:35.999 from Node.js or npm because they are so common. 13:36.000 --> 00:13:41.044 I don't quite like that. 00:13:41.144 --> 00:13:45.364 Another reason for favoring Emacs clients 00:13:45.464 --> 00:13:48.999 over JavaScript clients is user freedom. 13:49.000 --> 00:13:53.284 Emacs is geared towards user freedom. 00:13:53.384 --> 00:14:01.564 It allows users maximum freedom to customize or mod Emacs. 00:14:01.664 --> 00:14:07.164 I think Emacs clients can be a way to fix JavaScript traps, 00:14:07.264 --> 00:14:14.244 like using user scripts to replace non-free JavaScript. 00:14:14.344 --> 00:14:19.484 There are tools to do that, for example, like Haketilo. 00:14:19.584 --> 00:14:21.404 Why write JavaScript replacement 00:14:21.504 --> 00:14:25.164 if we can write Elisp replacement? 00:14:25.264 --> 00:14:31.684 If we overwrite all kinds of front-ends in Emacs 00:14:31.784 --> 00:14:34.404 for commonly-used web applications 00:14:34.504 --> 00:14:36.999 like Reddit, Hacker News, what have you, 14:37.000 --> 00:14:40.804 then we have an Emacs app store 00:14:40.904 --> 00:14:43.604 where we can just install these applications 00:14:43.704 --> 00:14:51.084 and browse the web more freely. 00:14:51.184 --> 00:14:56.044 Back to hcel, which is the Emacs client I wrote. 00:14:56.144 --> 00:14:59.084 I tried to reuse as much of Emacs built-ins as possible, 00:14:59.184 --> 00:15:03.044 including eldoc, for showing documentation, 00:15:03.144 --> 00:15:04.764 xref for cross-referencer, 00:15:04.864 --> 00:15:06.999 compilation-mode for showing search results of identifiers, 15:07.000 --> 00:15:11.604 outline-mode for a hierarchical view 00:15:11.704 --> 00:15:14.284 of package module identifiers, 00:15:14.384 --> 00:15:17.999 sort of a cursor-mode for highlighting identifiers, 15:18.000 --> 00:15:26.044 help-mode for displaying quick help for Haskell identifiers, 00:15:26.144 --> 00:15:27.604 integration with haddorg, 00:15:27.704 --> 00:15:31.204 which I will mention later, etc. 00:15:31.304 --> 00:15:37.999 It is available as hcel without the dot on GNU ELPA. 15:38.000 --> 00:15:40.084 Time for a demo. 00:15:40.184 --> 00:15:42.484 To start using hc.el, surprise surprise, 00:15:42.584 --> 00:15:45.084 we run the hcel command. 00:15:45.184 --> 00:15:46.884 We are presented with a list of packages 00:15:46.984 --> 00:15:51.999 indexed by the hcel indexer. 15:52.000 --> 00:15:53.964 This is an outline mode, 00:15:54.064 --> 00:15:58.724 so we can tab to list all the modules 00:15:58.824 --> 00:16:00.999 represented by the module path. 16:01.000 --> 00:16:03.404 We can further tab into the list of identifiers 00:16:03.504 --> 00:16:04.999 declared in this module. 16:05.000 --> 00:16:09.084 Now it asks whether you want to open module source. 00:16:09.184 --> 00:16:11.884 This is because some module source code 00:16:11.984 --> 00:16:13.999 can be quite large and it can take a bit of time. 16:14.000 --> 00:16:17.684 In this case, the control monad is quite small, 00:16:17.784 --> 00:16:19.844 so let's say yes. 00:16:19.944 --> 00:16:24.004 We see the list of identifiers. 00:16:24.104 --> 00:16:27.999 One can jump to an identifier forever. 16:28.000 --> 16:32.999 As you can see, the identifiers at points are highlighted. 16:33.000 --> 00:16:36.124 This can be particularly useful 00:16:36.224 --> 00:16:38.604 in a large function declaration 00:16:38.704 --> 00:16:39.999 where you come to see, for example, 16:40.000 --> 00:16:44.204 all the occurrences of an identifier 00:16:44.304 --> 00:16:47.999 inside the body of the declaration. 16:48.000 --> 00:16:50.724 These are declarations 00:16:50.824 --> 00:16:52.999 which in Haskell mode are listed in imenu. 16:53.000 --> 16:59.999 We can do the same here in hcel source mode. 17:00.000 --> 17:05.999 It lists all the declarations with their signature. 17:06.000 --> 17:12.999 Let's say we want to jump to this funny operator. 17:13.000 --> 00:17:20.324 It worked and you can also go back and forth 00:17:20.424 --> 00:17:25.999 within the declarations by pressing "n" and "p". 17:26.000 --> 00:17:30.804 Similarly, you can do something similar in the outline mode 00:17:30.904 --> 00:17:37.999 by toggling the follow mode, just like in org-agenda. 17:38.000 --> 00:17:40.124 Let's turn it off. 00:17:40.224 --> 00:17:45.999 Now, how about find definition references? 17:46.000 --> 00:17:48.964 Using xref, 00:17:49.064 --> 00:17:52.999 we can jump to the definition of Int and jump back. 17:53.000 --> 17:55.999 Jump to Maybe, jump back. 17:56.000 --> 00:18:00.924 Let's have a look at references of replicateM. 00:18:01.024 --> 00:18:03.364 There are plenty of them. 00:18:03.464 --> 00:18:08.999 Maybe we want to check out ghc-lib. 18:09.000 --> 00:18:11.244 Here are all the references 00:18:11.344 --> 00:18:15.999 and you can of course jump to any of them in the results. 18:16.000 --> 18:18.999 Cool. 18:19.000 --> 00:18:21.764 You may have already noticed 00:18:21.864 --> 00:18:27.084 the eldoc displaying the documentation 00:18:27.184 --> 00:18:34.804 and signature of identifiers. 00:18:34.904 --> 00:18:44.004 For example, here it shows the signature of replicateM, 00:18:44.104 --> 00:18:46.999 where it is defined, and its documentation. 18:47.000 --> 18:55.999 We can bring up the eldoc buffer. 18:56.000 --> 00:18:58.164 In the eldoc buffer, 00:18:58.264 --> 00:19:00.084 there are also links to other identifiers, 00:19:00.184 --> 00:19:04.444 which takes you to the definition of these identifiers, 00:19:04.544 --> 00:19:07.524 like minBound. 00:19:07.624 --> 00:19:10.764 Apparently, this is not working. 00:19:10.864 --> 00:19:13.004 I'm pretty sure it maybe works. 00:19:13.104 --> 00:19:16.999 Let's go to nothing or just... 19:17.000 --> 00:19:19.764 I think those didn't work because 00:19:19.864 --> 00:19:24.044 the module source for those identifiers is not open. 00:19:24.144 --> 00:19:30.204 Of course, you can search 00:19:30.304 --> 00:19:32.924 for any identifiers across all indexed packages 00:19:33.024 --> 00:19:37.999 by invoking hcel-global-ids. 19:38.000 --> 19:41.999 Let's say we want to search for Read. 19:42.000 --> 00:19:47.364 We are presented with a list of results, 00:19:47.464 --> 00:19:53.999 which are identifiers starting with Read with capital R. 19:54.000 --> 00:19:57.204 They also show where they are defined 00:19:57.304 --> 00:20:06.999 and the documentation, just like in eldoc. 20:07.000 --> 00:20:13.844 One can also directly jump to the identifier 00:20:13.944 --> 00:20:19.999 in the mini-buffer results. 20:20.000 --> 00:20:21.924 For example, we want to check out this Read2 00:20:22.024 --> 00:20:27.999 defined in base-4.12.0.0 Data.Functor.Classes 20:28.000 --> 20:33.999 There we go. 20:34.000 --> 00:20:37.764 Another functionality of hcel 00:20:37.864 --> 00:20:40.999 is the help buffer integration. 20:41.000 --> 00:20:46.564 We can do hcel-help and then let's say 00:20:46.565 --> 00:20:52.644 we want to learn about the read type class. 00:20:52.744 --> 00:20:55.084 This is a help buffer 00:20:55.184 --> 00:21:00.804 and you can jump to other definitions 00:21:00.904 --> 00:21:02.364 within the help buffer 00:21:02.464 --> 00:21:06.999 to read the documentation like readsPrec. 21:07.000 --> 21:10.999 It says Server version cannot be satistifed. Actual version. 21:11.000 --> 00:21:14.684 This means we need to tell hecl 00:21:14.784 --> 00:21:16.999 that the server has the correct version. 21:17.000 --> 00:21:21.644 hecl-fetch-server-version. 00:21:21.744 --> 00:21:25.604 Wait a bit for it to update 00:21:25.704 --> 00:21:26.999 the knowledge of the server version. 21:27.000 --> 21:32.999 Now you can follow the links, Read, readsPrec. 21:33.000 --> 21:37.999 You can do the "l" and "r" to navigate within the history. 21:38.000 --> 21:42.999 ReadS, ReadP. 21:43.000 --> 00:21:45.924 Just like in the help buffer for elisp code, 00:21:46.024 --> 00:21:52.999 you can jump to the definition. 21:53.000 --> 21:59.999 I believe that is everything, more or less. 22:00.000 --> 22:04.999 That concludes the demo. 22:05.000 --> 00:22:07.044 Now let's turn to haddorg, 00:22:07.144 --> 00:22:08.999 which is an Org backend for Haddock. 22:09.000 --> 22:12.999 Haddock is the documentation generator for Haskell packages. 22:13.000 --> 00:22:15.044 For example, 00:22:15.144 --> 00:22:21.999 the official Haskell package documentation website Hackage, 22:22.000 --> 00:22:25.804 all the documentation there is generated by Haddock 00:22:25.904 --> 00:22:27.999 into the HTML format. 22:28.000 --> 00:22:31.324 Haddock has several backends 00:22:31.424 --> 00:22:34.284 that convert the intermediate representation 00:22:34.384 --> 00:22:36.964 called interface to various output formats, 00:22:37.064 --> 00:22:41.764 including HTML, LaTeX, and Hugo. 00:22:41.864 --> 00:22:44.804 HTML is the main format with a lot of features. 00:22:44.904 --> 00:22:48.999 LaTeX is less so, and I don't think it is widely used. 22:49.000 --> 22:52.999 Let's have a look at an HTML example. 22:53.000 --> 00:23:01.084 This is a PDF because these HTML files can be rather large 00:23:01.184 --> 00:23:06.999 and slow down EWW significantly. 23:07.000 --> 00:23:10.164 It's faster to convert it to PDF 00:23:10.264 --> 00:23:16.999 and read it from pdf-tools. 23:17.000 --> 00:23:20.764 Looks like this is as big as it goes. 00:23:20.864 --> 00:23:26.044 I hope you can still see it. 00:23:26.144 --> 00:23:30.044 Can I still enlarge it a bit more? Maybe. 00:23:30.144 --> 00:23:32.964 This is Servant.Server. 00:23:33.064 --> 00:23:35.999 It is a module in the servant-server package. 23:36.000 --> 23:41.999 It is a widely used package for writing servers. 23:42.000 --> 00:23:49.804 It starts with a heading, which is the name of the module, 00:23:49.904 --> 00:23:52.684 and the table of contents. 00:23:52.784 --> 00:23:55.999 Then a heading: Run an wai application from an API. 23:56.000 --> 00:24:00.804 Under this heading, there are all the relevant identifiers 00:24:00.904 --> 00:24:08.524 that is concerned with running a WAI application from API, 00:24:08.624 --> 00:24:13.204 including serve, which is one of the main entry points 00:24:13.304 --> 00:24:15.524 for a Servant.Server. 00:24:15.624 --> 00:24:21.604 It has a signature linkable to the other identifiers, 00:24:21.704 --> 00:24:23.004 the documentation, 00:24:23.104 --> 00:24:26.644 an example with a Haskell source code block. 00:24:26.744 --> 00:24:30.999 That's what HTML output looks like. 24:31.000 --> 00:24:33.924 As I mentioned, 00:24:34.024 --> 00:24:35.804 there are several downsides or drawbacks with that, 00:24:35.904 --> 00:24:40.999 like the HTML files can be huge and slow down EWW. 24:41.000 --> 00:24:46.124 Also, every module is an HTML of itself, 00:24:46.224 --> 00:24:48.284 and there's also an HTML for the package 00:24:48.384 --> 00:24:49.999 with a list of all the modules. 24:50.000 --> 00:24:54.644 Whereas the Org backend 00:24:54.744 --> 00:25:04.164 is better in that it is much more compact. 00:25:04.264 --> 00:25:07.404 All the modules under the same package 00:25:07.504 --> 00:25:10.684 are included in one Org file 00:25:10.784 --> 00:25:12.999 as sub-headings, level 2 headings. 25:13.000 --> 00:25:19.404 So, servant-server, Servant.Server, that is the module. 00:25:19.504 --> 00:25:21.844 So basically, this level 2 heading 00:25:21.944 --> 00:25:24.999 contains all the information in this PDF. 25:25.000 --> 25:28.999 Run the WAI application from API, serve. 25:29.000 --> 00:25:39.124 It has a signature that links to other identifiers 00:25:39.224 --> 00:25:41.999 and the documentation that's also linkable. 25:42.000 --> 00:25:47.124 The Haskell source block is now an Org source block, 00:25:47.224 --> 00:25:49.404 and you can do all sorts of interesting things 00:25:49.504 --> 00:25:52.644 with it using org-babel. 00:25:52.744 --> 00:25:55.999 Let's check the links as server. 25:56.000 --> 25:59.999 Right, so the link works. 26:00.000 --> 00:26:05.284 Application, right, Request. 00:26:05.384 --> 00:26:08.284 It also supports cross-packaging package linking, 00:26:08.384 --> 00:26:12.204 so following the link to request 00:26:12.304 --> 00:26:17.524 takes us from servant-server package Org documentation 00:26:17.624 --> 00:26:24.684 to the WAI Org documentation. 00:26:24.784 --> 00:26:27.444 Another nice thing with Org documentation 00:26:27.544 --> 00:26:32.644 is that you can use Org functions 00:26:32.744 --> 00:26:40.444 like org-goto to jump to any identifiers. 00:26:40.544 --> 00:26:45.804 Let's say we want to jump to application. 00:26:45.904 --> 00:26:49.999 We have toApplication. So it jumpts to toApplication. 26:50.000 --> 00:26:53.924 I guess application is not an identifier, 00:26:54.024 --> 00:26:55.724 yes, it is more like a type alias, 00:26:55.824 --> 00:26:58.564 that's why we couldn't find it. 00:26:58.664 --> 00:27:00.999 So that is haddorg. 27:01.000 --> 00:27:06.004 And of course, I implemented a bit of integration 00:27:06.104 --> 00:27:08.444 between haddorg and hcel 00:27:08.544 --> 00:27:11.204 so that we can jump from one to the other. 00:27:11.304 --> 00:27:14.999 Let's go back to servant. 27:15.000 --> 27:23.999 Let's see, ServerT. 27:24.000 --> 00:27:27.004 Maybe we want to check out 00:27:27.104 --> 00:27:31.844 the source code definition of ServerT. 00:27:31.944 --> 00:27:36.164 To find out exactly what sort of type alias it is, 00:27:36.264 --> 00:27:43.084 like what is the alias (or type synonym) 00:27:43.184 --> 00:27:49.404 We run hcel-identifier-at-point-- 00:27:49.504 --> 00:27:52.244 sorry, hcel-haddorg-to-hcel-definition... 00:27:52.344 --> 00:27:54.999 Oh, we have an HTTP error. 27:55.000 --> 27:58.999 Typ ServerT not found in module src/Servant/Server.hs 27:59.000 --> 00:28:01.124 Why? Well, this is because 00:28:01.125 --> 00:28:04.844 the HCEL server only understands, 00:28:04.944 --> 00:28:07.724 it only has knowledge of identifiers 00:28:07.824 --> 00:28:11.999 that is defined in the original source file. 28:12.000 --> 00:28:17.084 So, it is not aware of, say, 00:28:17.184 --> 00:28:20.999 identifiers that are re-exported in the module. 28:21.000 --> 00:28:25.724 Most likely, Servant.Server module re-exports ServerT 00:28:25.824 --> 00:28:28.604 from another module. 00:28:28.704 --> 00:28:29.644 We will probably have better luck 00:28:29.744 --> 00:28:34.999 looking into some internal modules like this one. 28:35.000 --> 28:38.999 Let's try this type class HasContextEntry. 28:39.000 --> 28:41.999 So this time it worked. 28:42.000 --> 00:28:44.244 And, of course, we can go the other direction 00:28:44.344 --> 00:28:47.999 from hecl to haddorg. 28:48.000 --> 00:28:51.484 Let's say if we want to display named context 00:28:51.584 --> 00:28:53.999 in the haddorg documentation 28:54.000 --> 00:29:01.524 so that we can read about, other identifiers documentation 00:29:01.624 --> 00:29:03.999 that is related to named context. 29:04.000 --> 29:07.999 We do hecl-identifier-at-point-to-haddorg 29:08.000 --> 29:13.999 And it does take us to the server-server old file. 29:14.000 --> 29:17.999 Okay. 29:18.000 --> 29:20.999 And that concludes my presentation. 29:21.000 --> 00:29:23.484 You can find hecl in GNU Elpa, 00:29:23.584 --> 00:29:24.999 and you can also find the source code, 29:25.000 --> 00:29:27.364 as well as the source of haddorg 00:29:27.464 --> 00:29:29.764 and instructions on how to generate org documentation 00:29:29.864 --> 00:29:32.999 using haddorg in my cgit instance. 29:33.000 --> 00:29:36.684 Thank you for your attention. 00:29:36.784 --> 00:29:37.999 I hope you enjoy the rest of the conference. 29:38.000 --> 29:51.000 Thank you.