<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: German Robayo</title>
    <description>The latest articles on DEV Community by German Robayo (@german1608).</description>
    <link>https://dev.to/german1608</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F400809%2F2ba727bc-2eb9-465b-8e9b-28062c376816.jpeg</url>
      <title>DEV Community: German Robayo</title>
      <link>https://dev.to/german1608</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/german1608"/>
    <language>en</language>
    <item>
      <title>Season finale: Dhall documentation generator</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Wed, 26 Aug 2020 12:45:59 +0000</pubDate>
      <link>https://dev.to/german1608/season-finale-dhall-documentation-generator-2lfn</link>
      <guid>https://dev.to/german1608/season-finale-dhall-documentation-generator-2lfn</guid>
      <description>&lt;p&gt;This is my last post and final report as part of GSoC 2020, working on the &lt;a href="https://summerofcode.withgoogle.com/projects/#5366051979657216"&gt;Dhall documentation generator&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Initial problem
&lt;/h1&gt;

&lt;p&gt;Dhall is a relatively new language. The only way to see how to use a Dhall package was to manually inspect the code and reading the comments. The &lt;a href="https://github.com/dhall-lang/dhall-lang/tree/v17.1.0/Prelude"&gt;Dhall Prelude&lt;/a&gt; is a good example of this approach by adding a comment to its headers as shown in &lt;a href="https://github.com/dhall-lang/dhall-lang/blob/2cb2e1804aa5ba8379137df1fc1fd1e9afb17ec7/Prelude/List/concatMap.dhall#L1-L4"&gt;this&lt;/a&gt; example. Some package doesn't even have comments, so you'd need to actually read the code to see how to use the package.&lt;/p&gt;

&lt;h1&gt;
  
  
  Main contribution
&lt;/h1&gt;

&lt;p&gt;As part of my GSoC project, I built &lt;code&gt;dhall-docs&lt;/code&gt; that takes a Dhall package and generates HTML documentation by running static analysis over each file on the package. The tool has the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes a folder with Dhall files, extracts its headers and outputs HTML that will render that documentation (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1845"&gt;#1845&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Renders the HTML with some simple CSS and JS that improves the UI/UX (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1848"&gt;#1848&lt;/a&gt;, &lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1895"&gt;#1895&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The index's dhall files section includes the type of each file (extracted from source code) (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1898"&gt;#1898&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Assert expressions are extracted and rendered in a dedicated section in the generated HTML (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1899"&gt;#1899&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A comment's syntax specification was created to correctly handle indentation before using a Markdown parser (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1929"&gt;#1929&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Renders the source code with jump-to-definition (JTD) capabilities on the following places:

&lt;ul&gt;
&lt;li&gt;Import expressions (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1959"&gt;#1959&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Let binding names (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1966"&gt;#1966&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Lambda argument names (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1982"&gt;#1982&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Record (literals and types) field names (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1991"&gt;#1991&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Besides the work outlined in the PRs of the above list, I made the following technical improvements to the &lt;code&gt;dhall-docs&lt;/code&gt; package at the &lt;a href="https://github.com/dhall-lang/dhall-haskell"&gt;&lt;code&gt;dhall-haskell&lt;/code&gt;&lt;/a&gt; repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;a href="https://softwareengineering.stackexchange.com/questions/358786/what-is-golden-files"&gt;golden tests&lt;/a&gt; setup to ensure that the generated documentation is preserved through code changes (&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1899"&gt;#1899&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Generate documentation for the &lt;a href="https://hydra.dhall-lang.org/job/dhall-haskell/master/prelude-dhall-docs/latest/download/1/docs"&gt;Prelude&lt;/a&gt;, &lt;a href="https://hydra.dhall-lang.org/job/dhall-haskell/master/kubernetes-dhall-docs/latest/download/1/docs"&gt;&lt;code&gt;dhall-kubernetes&lt;/code&gt;&lt;/a&gt;, and the &lt;a href="https://hydra.dhall-lang.org/build/70746/download/1/docs/"&gt;test demo package&lt;/a&gt; that the golden-test setup of &lt;code&gt;dhall-docs&lt;/code&gt; uses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list of all PRs I authored on the &lt;a href="https://github.com/dhall-lang/dhall-haskell"&gt;&lt;code&gt;dhall-haskell&lt;/code&gt;&lt;/a&gt; repository can be found &lt;a href="https://github.com/dhall-lang/dhall-haskell/pulls?q=is%3Apr+author%3Agerman1608+"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...and I made some upstream changes to the &lt;a href="https://github.com/dhall-lang/dhall-lang"&gt;Dhall Language Standard&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add more tests for record field labels (&lt;a href="https://github.com/dhall-lang/dhall-lang/pull/1013"&gt;#1013&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;And changes related to how does &lt;code&gt;dhall-docs&lt;/code&gt; manages packages (&lt;a href="https://github.com/dhall-lang/dhall-lang/pull/1026"&gt;#1026&lt;/a&gt;, &lt;a href="https://github.com/dhall-lang/dhall-lang/pull/1053"&gt;#1053&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I openly and actively discussed things related to &lt;code&gt;dhall-docs&lt;/code&gt; behavior not only with my mentors but with the wide community via Discourse posts. The most relevant posts were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discourse.dhall-lang.org/t/dhall-docs-cli-utility/267"&gt;The first discussion about the &lt;code&gt;dhall-docs&lt;/code&gt; goals and my introduction to the community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discourse.dhall-lang.org/t/announcing-the-first-experimental-release-of-dhall-docs/300"&gt;The announcement of the first release of &lt;code&gt;dhall-docs&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to see my messages on discourse.dhall-lang.org, go &lt;a href="https://discourse.dhall-lang.org/u/german1608/activity"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...and to end this section, although it's not directly related to my project, I familiarized myself with the existing codebase by taking small issues on the community bonding period. I already talked about that in &lt;a href="https://dev.to/german1608/prelude-48a1"&gt;this&lt;/a&gt; post.&lt;/p&gt;

&lt;p&gt;All the source code can be found &lt;a href="https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-docs"&gt;here&lt;/a&gt;. We already have a release of &lt;code&gt;dhall-docs&lt;/code&gt; (on a &lt;a href="https://github.com/dhall-lang/dhall-haskell/releases/tag/1.34.0"&gt;GitHub release&lt;/a&gt; and on &lt;a href="https://hackage.haskell.org/package/dhall-docs"&gt;Hackage&lt;/a&gt;) &lt;strong&gt;but&lt;/strong&gt; it doesn't contain all features. We're waiting for &lt;a href="https://github.com/dhall-lang/dhall-lang/pull/1059"&gt;this release PR on the standard&lt;/a&gt; to be merged to make another release of the &lt;a href="https://github.com/dhall-lang/dhall-haskell"&gt;&lt;code&gt;dhall-haskell&lt;/code&gt;&lt;/a&gt; packages, including &lt;code&gt;dhall-docs&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pending work
&lt;/h1&gt;

&lt;p&gt;If we compare the work done vs. my proposal, the things that are missing are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax-highlighting on rendered source code. We had it at the beginning, but adding jump-to-definition required changing how we render source code. It is still possible to add this with the current &lt;code&gt;fragments&lt;/code&gt; function used for JTD&lt;/li&gt;
&lt;li&gt;Type-on-hover. We have a &lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/2005"&gt;WIP PR&lt;/a&gt; that I couldn't finish, although it's in good shape.&lt;/li&gt;
&lt;li&gt;Read comments from other places in the source-code. In this moment, &lt;code&gt;dhall-docs&lt;/code&gt; only supports the Header comment of the file, and it would be great to add support for other places such as record fields, lambdas and function-type arguments. The most difficult part for this work is to properly preserve whitespace, but &lt;a href="https://github.com/dhall-lang/dhall-haskell/issues/145#issuecomment-660479611"&gt;we're making progress&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Jump-to-definition on expressions that involve imports. We currently jump to another URL when the clicked expression is a relative and remote import. But things like &lt;code&gt;(./Import.dhall).field.deep&lt;/code&gt; are not handled yet and it would be really useful. A common pattern seen on dhall packages is that they use a &lt;code&gt;package.dhall&lt;/code&gt; file that contains every file in the package, and using the above example with it can improve navigability a lot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm not sad that these features weren't done. I made a couple of improvements on the Dhall parser to preserve more whitespace that &lt;code&gt;dhall-docs&lt;/code&gt; needed for JTD and that took more weeks as expected. The best part is that the work done there can also be used to fix a &lt;a href="https://github.com/dhall-lang/dhall-haskell/issues/145"&gt;long-standing&lt;/a&gt; issue on the &lt;code&gt;dhall format&lt;/code&gt; command. It was a good trade-off, after all 😄&lt;/p&gt;

&lt;h1&gt;
  
  
  Screenshots &amp;amp; Demo package
&lt;/h1&gt;

&lt;p&gt;The following are some screenshots of how the generated documentation looks. These were taken from the &lt;a href="https://github.com/dhall-lang/dhall-haskell"&gt;&lt;code&gt;dhall-haskell&lt;/code&gt;&lt;/a&gt; CI/CD results for the &lt;code&gt;dhall-docs&lt;/code&gt; execution on sample packages, and since the job is not updated with the latest &lt;a href="https://github.com/dhall-lang/dhall-lang"&gt;&lt;code&gt;dhall-lang&lt;/code&gt;&lt;/a&gt; commit, almost all links on relative imports are broken (&lt;code&gt;dhall-docs&lt;/code&gt; doesn't report broken links)&lt;/p&gt;

&lt;p&gt;The Dhall Prelude package index:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kC1YExWd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yqcxff0uo297c65e60vu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kC1YExWd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yqcxff0uo297c65e60vu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Prelude/Bool/package.dhall&lt;/code&gt; is essentially a sub-package inside &lt;code&gt;Prelude&lt;/code&gt; and it re-exports all files inside &lt;code&gt;Prelude/Bool&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wQEgTCnH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qsrutb9s5h0iolwa6viv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wQEgTCnH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qsrutb9s5h0iolwa6viv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Prelude/Bool/fold&lt;/code&gt; is really complete as it shows the extracted header as markdown, assertions, and jump-to-definition capabilities:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XDmQ7Ke2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kwjk9zrh2czfekvahgx1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XDmQ7Ke2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kwjk9zrh2czfekvahgx1.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the &lt;a href="https://hydra.dhall-lang.org/build/70746/download/1/docs/"&gt;test demo package&lt;/a&gt; a good example of jump-to-definition on record fields is the "jump-to-definition with nested labels":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gJV7Q8wn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h4tmb5ek42hn91ztfeir.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gJV7Q8wn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h4tmb5ek42hn91ztfeir.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can use relative imports links to navigate to another expression in the same package:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nnST-IwY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/edq7tpiniacxo91gpmlz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nnST-IwY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/edq7tpiniacxo91gpmlz.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;I still remember that I literally yelled at my room after receiving the email from the GSoC team that my proposal was accepted, and a lot of things have changed since then. The German from that moment wouldn't believe all the things that He learned during these last 4 months, not only about Haskell but about Open Source projects.&lt;/p&gt;

&lt;p&gt;The most important part of an Open Source project is its community: without it, a project is just a bunch of code. And it's difficult to be proactive (quoting from Gabriel, my mentor) if you're not really passionate or if you don't get any funds from it. Google's initiative on this program helps a lot of projects finish their ongoing issues, and to offer new issues for arising tools (such as Dhall, for instance).&lt;/p&gt;

&lt;p&gt;Contributing to Open Source for the first time may be complicated, but once you get used to it it's really simple and you get a lot of benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be a member of a community&lt;/li&gt;
&lt;li&gt;Help your favorite ecosystem grows&lt;/li&gt;
&lt;li&gt;Improve your career in technical and non-technical aspects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before contributing to &lt;a href="https://github.com/dhall-lang/dhall-haskell"&gt;&lt;code&gt;dhall-haskell&lt;/code&gt;&lt;/a&gt;, my Haskell experiences came from university projects. I could say that those projects used ok-ish Haskell: I'm really proud of those. I didn't have somebody reviewing my code, and I felt that a lot of things could be improved and I didn't have any point of comparison.&lt;/p&gt;

&lt;p&gt;When I cloned &lt;a href="https://github.com/dhall-lang/dhall-haskell"&gt;&lt;code&gt;dhall-haskell&lt;/code&gt;&lt;/a&gt; and opened any file I knew that this was completely new to me. Things such as LANGUAGE pragmas were completely unknown. Even things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cp"&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;

&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Text&lt;/span&gt;
&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"string literal"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;confused me a lot at the beginning (how a &lt;code&gt;String&lt;/code&gt; is compatible with &lt;code&gt;Data.Text.Text&lt;/code&gt;???????), though right now it's really simple!&lt;/p&gt;

&lt;p&gt;Working properly with Functors, Applicatives, and Monads (even implementing my own!) were things that I wanted to do so many time ago, and after a couple of PRs on the repository started to feel really natural (not a pro, yet).&lt;/p&gt;

&lt;p&gt;I started creating more data-types to make illegal states unrepresentable, a thing that I felt afraid (I over-abused &lt;code&gt;Maybe&lt;/code&gt; and &lt;code&gt;[]&lt;/code&gt; on my old projects) and lenses, although I didn't use them a lot for &lt;code&gt;dhall-docs&lt;/code&gt;, stopped to scaring me.&lt;/p&gt;

&lt;p&gt;There are even more things that I could write, but I don't want this post longer than it currently is.&lt;/p&gt;

&lt;p&gt;Although this is the end of my work on the GSoC program, I'm pretty sure that I'll keep contributing in the short-coming future&lt;/p&gt;

&lt;h1&gt;
  
  
  Acknowledgments
&lt;/h1&gt;

&lt;p&gt;To my mentors &lt;a href="https://github.com/Gabriel439"&gt;Gabriel&lt;/a&gt;, &lt;a href="https://github.com/sjakobi"&gt;Simon&lt;/a&gt; and &lt;a href="https://github.com/Profpatsch"&gt;Philip&lt;/a&gt;: Thanks for the opportunity, for always being there and for your patience over all the project. Thanks for the guidance on the development of &lt;code&gt;dhall-docs&lt;/code&gt; and for telling me about your experiences on Open Source.&lt;/p&gt;

&lt;p&gt;To the Dhall community, to be proactive on their responses to my open-questions.&lt;/p&gt;

&lt;p&gt;To &lt;a href="https://haskell.org"&gt;Haskell.org&lt;/a&gt; for hosting the project and help me decide what project to choose 😉&lt;/p&gt;

&lt;p&gt;And last but not least: To Google for providing the GSoC program. It's a really good way to improve your career and help the Open Source community grow bigger and stronger.&lt;/p&gt;

&lt;p&gt;Thanks ❤️&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>dhall</category>
      <category>gsoc</category>
    </item>
    <item>
      <title>Jump to definition on source code</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Mon, 24 Aug 2020 15:35:14 +0000</pubDate>
      <link>https://dev.to/german1608/jump-to-definition-on-source-code-4fio</link>
      <guid>https://dev.to/german1608/jump-to-definition-on-source-code-4fio</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hi there! It's been a while since my &lt;a href="https://dev.to/german1608/comment-s-format-specification-20cj"&gt;last post&lt;/a&gt; and a cool feature that I've been working on recently it's roughly done, and it's really cool!&lt;/p&gt;

&lt;p&gt;The feature is jump-to-definition (I'll abbreviate that to JTD in the rest of the post), and it allows rendered source code to be more navigatable.&lt;/p&gt;

&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;To see some examples of this feature, you can visit the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Prelude.JSON.renderAs&lt;/code&gt; &lt;a href="https://hydra.dhall-lang.org/build/70743/download/1/docs/JSON/renderAs.dhall.html"&gt;https://hydra.dhall-lang.org/build/70743/download/1/docs/JSON/renderAs.dhall.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Every file with the &lt;code&gt;JumpTo&lt;/code&gt; prefix on this list &lt;a href="https://hydra.dhall-lang.org/build/70746/download/1/docs/"&gt;https://hydra.dhall-lang.org/build/70746/download/1/docs/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Jump to definition
&lt;/h1&gt;

&lt;p&gt;The main purpose of using a documentation generator for your projects (in any programming language) is to make it easy for your users to learn how to use your library/framework/package/whatsoever. Simple things such as analyzing source-code comments (as &lt;code&gt;dhall-docs&lt;/code&gt; already does) are good enough, but we can always add more features that make code discoverable and easier to read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jump to definition&lt;/strong&gt; is a feature that most documentation generators tools have. Let's use &lt;code&gt;haddock&lt;/code&gt; as an example: when &lt;code&gt;haddock&lt;/code&gt; generates the documentation of a Haskell packages it generates HTML for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The source-code comments that the user marked as &lt;strong&gt;documentation&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The actual source code of the package.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we use the &lt;code&gt;dhall&lt;/code&gt; package, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is the generated documentation for &lt;code&gt;Dhall.Core&lt;/code&gt; (which re-exports &lt;code&gt;Dhall.Syntax&lt;/code&gt;) &lt;a href="https://hackage.haskell.org/package/dhall-1.34.0/docs/Dhall-Core.html"&gt;https://hackage.haskell.org/package/dhall-1.34.0/docs/Dhall-Core.html&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;This is how &lt;code&gt;haddock&lt;/code&gt; renders the source code for the &lt;code&gt;Dhall.Syntax&lt;/code&gt; module &lt;a href="https://hackage.haskell.org/package/dhall-1.34.0/docs/src/Dhall.Syntax.html"&gt;https://hackage.haskell.org/package/dhall-1.34.0/docs/src/Dhall.Syntax.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you open the rendered source code for &lt;code&gt;Dhall.Syntax&lt;/code&gt;, you will see that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is rendered using syntax-highlighting&lt;/li&gt;
&lt;li&gt;It's full of links on the data-types and function names, which suggests you that it's clickable and it allows you to share the implementation of anything inside that module. For instance, you can see here the definition of the &lt;a href="https://hackage.haskell.org/package/dhall-1.34.0/docs/src/Dhall.Syntax.html#Expr"&gt;&lt;code&gt;Expr&lt;/code&gt;&lt;/a&gt; data type: the Dhall AST.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We want to add the same for &lt;code&gt;dhall-docs&lt;/code&gt;: take a file and do static analysis to see where each &lt;strong&gt;name&lt;/strong&gt; was defined, highlight it correctly when the user hovers it and jump to the definition of that name when the user clicks it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Dhall AST
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Expr&lt;/code&gt; data-type from the &lt;code&gt;dhall&lt;/code&gt; package contains a special constructor useful to get the source-span of a parsed expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Note&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(you can see its haddock &lt;a href="https://hackage.haskell.org/package/dhall-1.34.0/docs/src/Dhall.Syntax.html#Note"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The purpose of &lt;code&gt;Note&lt;/code&gt; is to create useful parse and type-errors by underlining the problematic expression. The Dhall parser outputs an &lt;code&gt;Expr Src Import&lt;/code&gt; (explanations of &lt;code&gt;Src&lt;/code&gt; and &lt;code&gt;Import&lt;/code&gt; can be found on &lt;code&gt;Expr&lt;/code&gt; &lt;a href="https://hackage.haskell.org/package/dhall-1.34.0/docs/src/Dhall.Syntax.html#Expr"&gt;haddock&lt;/a&gt;) where each meaningful expression is wrapped on a &lt;code&gt;Note&lt;/code&gt; constructor. &lt;code&gt;Src&lt;/code&gt;s contains metadata information about the parsed expression, such as source text and line and column numbers. For example, if you have the following expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 + 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;it will be parsed to something (roughly) like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="s"&gt;"1 + 2"&lt;/span&gt; &lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NaturalPlus&lt;/span&gt; &lt;span class="c1"&gt;-- for the `+` operator&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NaturalLit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NaturalLit&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Besides &lt;code&gt;Note&lt;/code&gt;, there are other constructors that preserve extra-information about the source code. It is mostly used by the &lt;code&gt;dhall format&lt;/code&gt; and &lt;code&gt;dhall lint&lt;/code&gt; commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code renderer
&lt;/h2&gt;

&lt;p&gt;Now the question is, how can I manipulate/traverse the &lt;code&gt;Expr&lt;/code&gt; in a way that lets me generates HTML for the following?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The declaration &amp;amp; use of names (variables)&lt;/li&gt;
&lt;li&gt;Relative imports&lt;/li&gt;
&lt;li&gt;The rest of the code, that should not be affected at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I first started making this simple data-type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- we will come to the ??? later&lt;/span&gt;
&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;SourceCodeType&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ImportExpr&lt;/span&gt; &lt;span class="kt"&gt;Dhall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Import&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;NameUse&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;NameDeclaration&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;SourceCodeFragment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;SourceCodeFragment&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt; &lt;span class="kt"&gt;SourceCodeType&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can think of each &lt;code&gt;SourceCodeFragment&lt;/code&gt; as a subsequent section of the source code. Similar to a &lt;strong&gt;token&lt;/strong&gt; (but not exactly that, though). Each one is discriminated by its &lt;code&gt;SourceCodeType&lt;/code&gt;, which carries the information of &lt;strong&gt;how&lt;/strong&gt; the code should be rendered in the HTML.&lt;/p&gt;

&lt;p&gt;Now we need to transform an &lt;code&gt;Expr Src Import&lt;/code&gt; to a &lt;code&gt;[SourceCodeFragment]&lt;/code&gt; and that's where the &lt;code&gt;fragments&lt;/code&gt; function comes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;fragments&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;SourceCodeFragment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The implementation of the &lt;code&gt;fragments&lt;/code&gt; function is quite large to fit in this post (110 lines, to be exact) but what it does is run a simple context-analysis on the AST to generate &lt;code&gt;SourceCodeFragment&lt;/code&gt; whenever a name was declared and used. It is clever enough to know when a name was not declared, and when a name was unused and showing no highlight on its HTML (i.e. not generating a &lt;code&gt;SourceCodeFragment&lt;/code&gt; for it).&lt;/p&gt;

&lt;p&gt;All the work is done in the &lt;code&gt;infer&lt;/code&gt; function, declared inside &lt;code&gt;fragments&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- explanation for ??? will come up later&lt;/span&gt;
&lt;span class="n"&gt;infer&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Dhall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Context&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Writer&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;SourceCodeFragment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Dhall.Context&lt;/code&gt; is a context table that allows us to insert and query for names when traversing an AST. We insert names when it makes sense to (i.e. let-bindings, record fields, and lambda parameters.&lt;/p&gt;

&lt;p&gt;All of this work allowed &lt;code&gt;dhall-docs&lt;/code&gt; to generate jump-to-definition for the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let-bindings&lt;/li&gt;
&lt;li&gt;Lambda argument names&lt;/li&gt;
&lt;li&gt;Record (literals and types) field names&lt;/li&gt;
&lt;li&gt;Imports (relative and remote imports)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see &lt;a href="https://hydra.dhall-lang.org/build/70746/download/1/docs/"&gt;here&lt;/a&gt; for a demo. The test cases are named with the feature that is being shown there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the &lt;code&gt;???&lt;/code&gt; on the code?
&lt;/h2&gt;

&lt;p&gt;let-binding and lambda argument names share the same JTD logic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calculate the source span position of the binding name&lt;/li&gt;
&lt;li&gt;Traverse the sibling expressions on both &lt;code&gt;Let&lt;/code&gt; and &lt;code&gt;Lam&lt;/code&gt; adding the name to the context accordingly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, adding support for record field is slightly different. We want to highlight the names where fields in selector-expressions were defined. In the following example we want to highlight &lt;code&gt;foo&lt;/code&gt; when the user hovers the &lt;code&gt;foo&lt;/code&gt; in the selector-expression &lt;code&gt;a.foo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;in&lt;/span&gt;  &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Pushing the &lt;code&gt;foo&lt;/code&gt; label to the context isn't the right solution because handling the exact expression to remote the &lt;code&gt;foo&lt;/code&gt; label would be complicated.&lt;/p&gt;

&lt;p&gt;What we instead do, is to use another data-type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;JtdInfo&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;RecordFields&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Set&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;NoInfo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;???&lt;/code&gt; corresponds to &lt;code&gt;JtdInfo&lt;/code&gt;. You can think of &lt;code&gt;JtdInfo&lt;/code&gt; as extra information recovered from the static-analysis that could aid in more precise generated JTD. Replacing &lt;code&gt;???&lt;/code&gt; on the above snippets, we got:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="kt"&gt;JtdInfo&lt;/span&gt;

&lt;span class="n"&gt;infer&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Dhall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Context&lt;/span&gt; &lt;span class="kt"&gt;NameDecl&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Writer&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;SourceCodeFragment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;JtdInfo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now each &lt;code&gt;NameDecl&lt;/code&gt; has an associated &lt;code&gt;JtdInfo&lt;/code&gt;, and every expression returns a &lt;code&gt;JtdInfo&lt;/code&gt; from &lt;code&gt;infer&lt;/code&gt;. Now we can pattern match against the &lt;code&gt;Field&lt;/code&gt; constructor to correctly setup JTD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;Field&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FieldSelection&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;srcEnd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;posStart&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;srcStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;posEnd&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;dhallType&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;infer&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;dhallType&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
      &lt;span class="kt"&gt;NoInfo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mempty&lt;/span&gt;
      &lt;span class="kt"&gt;RecordFields&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toList&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;

  &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeSrcForLabel&lt;/span&gt; &lt;span class="n"&gt;posStart&lt;/span&gt; &lt;span class="n"&gt;posEnd&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;
  &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NameDecl&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;
  &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NameDecl&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
      &lt;span class="kt"&gt;Writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tell&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;SourceCodeFragment&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NameUse&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
      &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
    &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;NoInfo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We setup JTD only if it makes sense. Thankfully pattern matching helps us elegantly handle all cases.&lt;/p&gt;

&lt;h1&gt;
  
  
  To end
&lt;/h1&gt;

&lt;p&gt;This was the last feature that I developed as part of my GSoC project. Keep in tune to read my last report about a summary of what the whole project and a story about all my experience through.&lt;/p&gt;

&lt;p&gt;Thanks for reading! &lt;/p&gt;

</description>
      <category>haskell</category>
      <category>dhall</category>
      <category>gsoc</category>
    </item>
    <item>
      <title>Comment's format specification</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Sun, 26 Jul 2020 06:27:02 +0000</pubDate>
      <link>https://dev.to/german1608/comment-s-format-specification-20cj</link>
      <guid>https://dev.to/german1608/comment-s-format-specification-20cj</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hi everyone! In this post, I'll write a summary of what I did this week on my GSoC project: Define and implement a specification for &lt;code&gt;dhall-docs&lt;/code&gt; comment's format.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why do we need a spec?
&lt;/h1&gt;

&lt;p&gt;Because of two particular reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distinguish between internal and documentation comments
&lt;/h2&gt;

&lt;p&gt;Is really common on several programming languages to write comments that you may not want to render in the language documentation generator. A simple way of avoiding so is by having "markers" on comments. Haddock, for instance, requires that you use &lt;code&gt;|&lt;/code&gt; as a marker in both single-line and block comments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cd"&gt;-- | Valid haddock comment&lt;/span&gt;

&lt;span class="c1"&gt;-- ignored haddock comment&lt;/span&gt;

&lt;span class="cm"&gt;{-| Valid haddock comment -}&lt;/span&gt;

&lt;span class="cm"&gt;{- Ignored haddock comment -}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Javadoc also does it, by requiring that Javadoc comments must start with &lt;code&gt;/**&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the same reason above, we need to be able to distinguish between internal and documentation comments on &lt;code&gt;dhall-docs&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Indentation issues
&lt;/h2&gt;

&lt;p&gt;We are going to use Markdown as a markup language for the documentation generator, specifically, We will use a particular flavor of Markdown named &lt;a href="https://commonmark.org/"&gt;CommonMark&lt;/a&gt;. Markdown, unlike Dhall, is sensitive to indentation. The following markdown document:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight markdown"&gt;&lt;code&gt;
first column
    4 columns later
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;will render "first column" in a normal paragraph, and "4 columns later" as an &lt;a href="https://spec.commonmark.org/0.12/#indented-code-blocks"&gt;Indented Code Block&lt;/a&gt;. I invite you to give it a try.&lt;/p&gt;

&lt;p&gt;In the beginning, since &lt;code&gt;dhall-docs&lt;/code&gt; only supports Header comments, we used the first column of the line as a base of indentation. That means that something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cm"&gt;{-
foo
bar
baz
-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;will be rendered as 3 different paragraphs, in different lines, whereas:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cm"&gt;{-
     foo
     bar
     baz
-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;will render all three lines in an indented-code-block. But to support other documentation comments (such as &lt;a href="https://dev.to/german1608/record-keys-prefix-whitespace-recovering-1o2g"&gt;record fields&lt;/a&gt;), this doesn't scale well. Take this example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;{-
            should this be indented???
            -}&lt;/span&gt;
            &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Comment's content indentation is now clear, and forcing users to write this case like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;{-
should this be indented???
            -}&lt;/span&gt;
            &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;is awful and was never an option.&lt;/p&gt;
&lt;h1&gt;
  
  
  Final specification
&lt;/h1&gt;

&lt;p&gt;Rewriting here the final specification is a non-sense, but you can read it &lt;a href="https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-docs"&gt;here&lt;/a&gt;. Block-comments were heavily based on Dhall's multiline strings to make it really familiar to something already implemented on the language. You can read here the specification for multiline strings &lt;a href="https://github.com/dhall-lang/dhall-lang/blob/master/standard/multiline.md#indentation"&gt;here&lt;/a&gt;. Single-line comments, on the other hand, was something completely new, or at least couldn't find anything similar from the Dhall's language design that could help, but I think that it will be comfortable for users.&lt;/p&gt;

&lt;p&gt;To give you a summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Block-comments starts with &lt;code&gt;{-|&lt;/code&gt; and a newline e.g.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{-|
foo
bar -}
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Single-line comments can span several lines, but the first one should init with &lt;code&gt;--|&lt;/code&gt; (note the final whitespace) and every other line should start with &lt;code&gt;--&lt;/code&gt; (note the two whitespaces). Also, they need to be vertically aligned e.g.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--| foo
--  bar
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;I have to admit: Text-manipulation is really hard and messy for me. My first implementation of the specification was really awful and cumbersome. One of my mentors gave me &lt;a href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/"&gt;this&lt;/a&gt; post about some tips on type-driven design and I applied them to the implementation. I heavily recommend reading that post.&lt;/p&gt;

&lt;p&gt;I defined the following data-type:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cp"&gt;{-# LANGUAGE DataKinds         #-}&lt;/span&gt;
&lt;span class="cp"&gt;{-# LANGUAGE KindSignatures    #-}&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;CommentType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;DhallDocsComment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;MarkedComment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;RawComment&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;ListOfSingleLineComments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NonEmpty&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SourcePos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;CommentType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;BlockComment&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;SingleLineComments&lt;/span&gt; &lt;span class="kt"&gt;ListOfSingleLineComments&lt;/span&gt;
    &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;

&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;DhallDocsText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;DhallDocsText&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note the Language extensions I'm using (disclaimer: I'm still learning Haskell and specifically the use of language extensions and some of them require some math background. I apologize if I say some nonsense. If you want to give me a term fix, please leave a comment on the post):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DataKinds&lt;/code&gt; allows us to extend Haskell's &lt;em&gt;kind&lt;/em&gt; system by promoting our data-types to kinds.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;KindSignatures&lt;/code&gt; allow the &lt;code&gt;a :: CommentType&lt;/code&gt; syntax. In that example it means "I accept any valid value of kind &lt;code&gt;CommentType&lt;/code&gt; i.e. &lt;code&gt;DhallDocsComment&lt;/code&gt;, &lt;code&gt;MarkedComment&lt;/code&gt;, &lt;code&gt;RawComment&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That allows us to have these type of comments:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="kt"&gt;RawComment&lt;/span&gt;
&lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="kt"&gt;MarkedComment&lt;/span&gt;
&lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="kt"&gt;DhallDocsComment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;and you know for sure what kind of text stores each possible type. This is something I love about Haskell: the type-system itself helps you write correct programs.&lt;/p&gt;

&lt;p&gt;After that, all left was doing some mappers between each possible &lt;code&gt;DhallComment&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- checks if a DhallComment has the `|` marker&lt;/span&gt;
&lt;span class="n"&gt;parseMarkedComment&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="kt"&gt;'RawComment&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="kt"&gt;'MarkedComment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- check that a MarkedComment is valid against the `dhall-docs` spec&lt;/span&gt;
&lt;span class="n"&gt;parseDhallDocsComment&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="kt"&gt;'MarkedComment&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="kt"&gt;CommentParseError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="kt"&gt;'DhallDocsComment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Manipulates the comment's text. Since the Comment&lt;/span&gt;
&lt;span class="c1"&gt;-- is a 'DhallDocsComment it should never fail&lt;/span&gt;
&lt;span class="n"&gt;parseDhallDocsText&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;DhallComment&lt;/span&gt; &lt;span class="kt"&gt;'DhallDocsComment&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;DhallDocsText&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;and to ensure that the implementation worked properly, the &lt;code&gt;dhall-docs&lt;/code&gt; test setup was enhanced to add several unit test cases for this which you can see &lt;a href="https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-docs/tasty/data/comments"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Examples of using this new spec
&lt;/h1&gt;

&lt;p&gt;Recently a PR was opened to modify the Dhall's Prelude header files. You can see the PR here:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/dhall-lang/dhall-lang/pull/1045"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Use `dhall-docs` comment format for Prelude
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1045&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/Gabriel439"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--BqXvHLiT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/1313787%3Fv%3D4" alt="Gabriel439 avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/Gabriel439"&gt;Gabriel439&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/dhall-lang/dhall-lang/pull/1045"&gt;&lt;time&gt;Jul 24, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;... so that the comment headers are included in the generated documentation&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/dhall-lang/dhall-lang/pull/1045"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h1&gt;
  
  
  To end
&lt;/h1&gt;

&lt;p&gt;I have 1 month left to finish the project and there are some core and cool features that are missing. As soon as I finish them I'll post here so you can check out. I have to say: I'm really excited to finish this project :)&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Record keys prefix whitespace recovering</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Sun, 26 Jul 2020 01:46:49 +0000</pubDate>
      <link>https://dev.to/german1608/record-keys-prefix-whitespace-recovering-1o2g</link>
      <guid>https://dev.to/german1608/record-keys-prefix-whitespace-recovering-1o2g</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hi folks! I haven't posted here since two weeks ago, so I'd like to give you an update on the progress of my #GSoC project.&lt;/p&gt;

&lt;p&gt;The main subject of this post is the recovering of prefix whitespace on Record keys, which will allow users to document record types and literals' keys.&lt;/p&gt;

&lt;h1&gt;
  
  
  First problem
&lt;/h1&gt;

&lt;p&gt;Haskell's Dhall's parser treats both block and single-line comments as whitespace, which ignores since Dhall's is whitespace insensitive.&lt;/p&gt;

&lt;p&gt;A limitation of this implementation is that we cannot fully reconstruct a Dhall file with the consumed whitespace and therefore the comments. This has been reported in some old issues on the repository. In particular, &lt;code&gt;dhall format&lt;/code&gt; removes comments after formatting the files&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/dhall-lang/dhall-haskell/issues/145" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        dhall-format removes comments
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#145&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/psibi" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars1.githubusercontent.com%2Fu%2F737477%3Fv%3D4" alt="psibi avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/psibi" rel="noopener noreferrer"&gt;psibi&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/dhall-lang/dhall-haskell/issues/145" rel="noopener noreferrer"&gt;&lt;time&gt;Sep 29, 2017&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Example file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--- This is dhall file
{ foo = "jax" }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Output it gives:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{ foo = "jax" }
&lt;/code&gt;&lt;/pre&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/dhall-lang/dhall-haskell/issues/145" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Due to the size of the project, some simple solutions for this have been made. The parser preserves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Header whitespace before the first non-whitespace character of the file. This is what &lt;code&gt;dhall-docs&lt;/code&gt; supports at this moment.&lt;/li&gt;
&lt;li&gt;Whitespaces in-between let-bindings components, as highlighted by &lt;a href="https://github.com/dhall-lang/dhall-haskell/blob/d028c6368acec125a1502e88a453be5ecbbf99e8/dhall/src/Dhall/Syntax.hs#L183-L198" rel="noopener noreferrer"&gt;this&lt;/a&gt; haddock comment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... but no more expressions have been handled yet because it's a little onerous to code and it introduces a lot of backward-incompatible changes.&lt;/p&gt;

&lt;p&gt;Two weeks ago, I started to add support to Record keys prefix on both record literals and types. The whole work is on the following PR&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1908" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(comments): support prefix comments on Record's key-value pairs.
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1908&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/german1608" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars2.githubusercontent.com%2Fu%2F29154504%3Fv%3D4" alt="german1608 avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/german1608" rel="noopener noreferrer"&gt;german1608&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1908" rel="noopener noreferrer"&gt;&lt;time&gt;Jul 10, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;This PR tries to add support to record field comments both on formatting and dhall-docs documentation extension. Specifically the following ones:&lt;/p&gt;
&lt;div class="highlight highlight-source-haskell js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;--&lt;/span&gt; before each record field&lt;/span&gt;
  a &lt;span class="pl-k"&gt;:&lt;/span&gt; &lt;span class="pl-ent"&gt;Text&lt;/span&gt;
  &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;--&lt;/span&gt; after each record field&lt;/span&gt;
, &lt;span class="pl-k"&gt;...&lt;/span&gt;
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;I updated the &lt;code&gt;Record&lt;/code&gt;'s &lt;code&gt;Expr&lt;/code&gt; constructor from:&lt;/p&gt;
&lt;div class="highlight highlight-source-haskell js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;Record&lt;/span&gt; (&lt;span class="pl-ent"&gt;Map&lt;/span&gt; &lt;span class="pl-ent"&gt;Text&lt;/span&gt; (&lt;span class="pl-ent"&gt;Expr&lt;/span&gt; s a))&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;to&lt;/p&gt;
&lt;div class="highlight highlight-source-haskell js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;Record&lt;/span&gt; (&lt;span class="pl-ent"&gt;Map&lt;/span&gt; &lt;span class="pl-ent"&gt;Text&lt;/span&gt; (&lt;span class="pl-ent"&gt;RecordField&lt;/span&gt; s a))&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;where &lt;code&gt;RecordField&lt;/code&gt; stores the last of the expression on the right side of the &lt;code&gt;:&lt;/code&gt; and the prefix and suffix comments. Although the prefix comment is annotating the label field, the best place to save that comment is there.&lt;/p&gt;
&lt;p&gt;However, I'm having a problem with &lt;code&gt;unsafeSubExpressions&lt;/code&gt;, because it can't traverse the &lt;code&gt;Maybe s&lt;/code&gt; I put on &lt;code&gt;RecordField&lt;/code&gt;. A quick solution for that is to change those &lt;code&gt;RecordField&lt;/code&gt;'s &lt;code&gt;Maybe s&lt;/code&gt;' to &lt;code&gt;Nothing&lt;/code&gt;, although that means we loose that information when traversing.&lt;/p&gt;
&lt;p&gt;I'll keep this PR as a draft to get your opinion in that matter.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/dhall-lang/dhall-haskell/pull/1908" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I made this because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It will be another element that &lt;code&gt;dhall-docs&lt;/code&gt; will document for&lt;/li&gt;
&lt;li&gt;It will help to fix the issue with &lt;code&gt;dhall format&lt;/code&gt; removing comments&lt;/li&gt;
&lt;li&gt;To take more knowledge of the whole &lt;code&gt;dhall&lt;/code&gt; codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the following sections, I'll describe how the task was made.&lt;/p&gt;

&lt;h1&gt;
  
  
  New data constructors
&lt;/h1&gt;

&lt;p&gt;The Dhall's AST constructors for Record literals and types are the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="c1"&gt;-- | &amp;gt; Record       [(k1, t1), (k2, t2)]        ~  { k1 : t1, k2 : t1 }&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Record&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;-- | &amp;gt; RecordLit    [(k1, v1), (k2, v2)]        ~  { k1 = v1, k2 = v2 }&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;RecordLit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They don't contain any property that will allow us to recover whitespace. So the first thing we need to do is to modify the constructors to include them. I ended up writing the following data-type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;RecordField&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;RecordField&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;recordFieldSrc&lt;/span&gt;  &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recordFieldValue&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Foldable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Lift&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;NFData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Ord&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Traversable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And modify the &lt;code&gt;Expr s a&lt;/code&gt; constructors like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="c1"&gt;-- | &amp;gt; Record [ (k1, RecordField _ t1)          ~  { k1 : t1, k2 : t1 }&lt;/span&gt;
    &lt;span class="c1"&gt;--   &amp;gt;        , (k2, RecordField _ t2)&lt;/span&gt;
    &lt;span class="c1"&gt;--   &amp;gt;        ]&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Record&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RecordField&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;-- | &amp;gt; RecordLit [ (k1, RecordField _ v1)       ~  { k1 = v1, k2 = v2 }&lt;/span&gt;
    &lt;span class="c1"&gt;--   &amp;gt;           , (k2, RecordField _ v2)&lt;/span&gt;
    &lt;span class="c1"&gt;--   &amp;gt;           ]&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;RecordLit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RecordField&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The captured whitespace is the prefix of the label. Although the &lt;code&gt;Map&lt;/code&gt; on the constructor maps labels to values, the less cumbersome place to save that was on the &lt;code&gt;RecordField&lt;/code&gt; data-type. This will allow us to map the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;-- my single-line before `a`&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To something (roughly) like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;RecordLit&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;RecordField&lt;/span&gt; &lt;span class="s"&gt;"-- my single-line before `a`"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NaturalLit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we don't save suffix whitespace right after each record value because the Dhall's parser consumes them and there is no pretty way that doesn't involve modifying a lot the parser to fix that. Thankfully, places like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="cm"&gt;{- A -}&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="cm"&gt;{- B -}&lt;/span&gt; &lt;span class="kt"&gt;B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will be easy to recover in the future and add value in the context of &lt;a href="https://github.com/dhall-lang/dhall-haskell/issues/145" rel="noopener noreferrer"&gt;#145&lt;/a&gt;. I didn't add support for those yet since I feel that people won't write a lot of useful documentation on that place, and I wanted to finish this as quickly as possible to start other tasks more directly related to my project.&lt;/p&gt;

&lt;p&gt;After modifying those records, the cumbersome part of the task came in: tracking the type-checking errors on the &lt;strong&gt;whole&lt;/strong&gt; project was exhausting. The good thing is that it wasn't difficult, and it helped me learn more about the whole project, which is good :)&lt;/p&gt;

&lt;h1&gt;
  
  
  Parser modifications
&lt;/h1&gt;

&lt;p&gt;Dhall's parser is located at the &lt;code&gt;Dhall.Parser.Expressions&lt;/code&gt; module. It is built using &lt;code&gt;megaparsec&lt;/code&gt; parser combinators. The relevant sections of the code are here on &lt;code&gt;alternative04&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;alternative04&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;_openBrace&lt;/span&gt;

    &lt;span class="n"&gt;src0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="n"&gt;whitespace&lt;/span&gt;
    &lt;span class="n"&gt;mComma&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;optional&lt;/span&gt; &lt;span class="n"&gt;_comma&lt;/span&gt;

    &lt;span class="c1"&gt;-- `src1` corresponds to the prefix whitespace of the first key-value&lt;/span&gt;
    &lt;span class="c1"&gt;-- pair. This is done to avoid using `try` to recover the consumed&lt;/span&gt;
    &lt;span class="c1"&gt;-- whitespace when the comma is not consumed&lt;/span&gt;
    &lt;span class="n"&gt;src1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;mComma&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="n"&gt;src0&lt;/span&gt;
        &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="n"&gt;whitespace&lt;/span&gt;

    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;recordTypeOrLiteral&lt;/span&gt; &lt;span class="n"&gt;src1&lt;/span&gt;

    &lt;span class="n"&gt;_closeBrace&lt;/span&gt;

    &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"literal"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;recordTypeOrLiteral&lt;/span&gt; &lt;span class="n"&gt;firstSrc0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;choice&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;emptyRecordLiteral&lt;/span&gt;
            &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonEmptyRecordTypeOrLiteral&lt;/span&gt; &lt;span class="n"&gt;firstSrc0&lt;/span&gt;
            &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;emptyRecordType&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the first snippet note that we parse the prefix whitespace of the &lt;em&gt;first&lt;/em&gt; key-value pair of the record, and pass it to the &lt;code&gt;recordTypeOrLiteral&lt;/code&gt; combinators. That allows us to share that whitespace over all possible &lt;code&gt;choice&lt;/code&gt;s on &lt;code&gt;recordTypeOrLiteral&lt;/code&gt; efficiently. If we didn't do that, we would recur to the &lt;code&gt;try&lt;/code&gt; function from &lt;code&gt;megaparsec&lt;/code&gt; that backtracks on parse failures, which increases the benchmark numbers.&lt;/p&gt;

&lt;p&gt;By doing all this work, the prefix whitespace of the record was preserved. You can check out that by using the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ -- I'm recovered
    a = 1,

    {- me too! -}
    b = 2,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...on &lt;code&gt;dhall haskell-syntax-tree --noted&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  To end
&lt;/h1&gt;

&lt;p&gt;This was a hard job. I feel great that I'm contributing not only to my particular project but the whole Dhall's Haskell's implementation.&lt;/p&gt;

&lt;p&gt;I'd like to thank my mentors Simon and Gabriel for their help with this PR not only by giving me suggestions and guidelines but on the exhausting job of reviewing that huge PR.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>gsoc</category>
      <category>dhall</category>
    </item>
    <item>
      <title>Announcing the first experimental release of dhall-docs 🎉</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Fri, 10 Jul 2020 14:15:25 +0000</pubDate>
      <link>https://dev.to/german1608/announcing-the-first-experimental-release-of-dhall-docs-3nmm</link>
      <guid>https://dev.to/german1608/announcing-the-first-experimental-release-of-dhall-docs-3nmm</guid>
      <description>&lt;p&gt;Hi there! This short post is to let you know that &lt;code&gt;dhall-docs&lt;/code&gt; was released 🎉.&lt;/p&gt;

&lt;p&gt;The tool is quite experimental yet, but you can start to generate useful documentation.&lt;/p&gt;

&lt;p&gt;For more information read this discourse post:&lt;br&gt;
&lt;a href="https://discourse.dhall-lang.org/t/announcing-the-first-experimental-release-of-dhall-docs/300?u=german1608"&gt;https://discourse.dhall-lang.org/t/announcing-the-first-experimental-release-of-dhall-docs/300?u=german1608&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to try &lt;code&gt;dhall-docs&lt;/code&gt; on your Dhall package and you'd like to give me feedback, please participate in the discourse post.&lt;/p&gt;

&lt;p&gt;Cheers 🥳&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Navigatable breadcrumbs and technical debts</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Thu, 09 Jul 2020 00:25:04 +0000</pubDate>
      <link>https://dev.to/german1608/navigatable-breadcrumbs-and-technical-debts-4ike</link>
      <guid>https://dev.to/german1608/navigatable-breadcrumbs-and-technical-debts-4ike</guid>
      <description>&lt;h1&gt;
  
  
  TL-DR
&lt;/h1&gt;

&lt;p&gt;If you want to see my current progress, check out here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hydra.dhall-lang.org/build/64022/download/1/docs/"&gt;https://hydra.dhall-lang.org/build/64022/download/1/docs/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  dhall-docs
&lt;/h1&gt;

&lt;p&gt;Hi there again! In this new post, I'm going to explain about two new features on &lt;code&gt;dhall-docs&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cleaner Haskell API;&lt;/li&gt;
&lt;li&gt;Navigatable breadcrumbs;&lt;/li&gt;
&lt;li&gt;Test-setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cleaner Haskell API
&lt;/h2&gt;

&lt;p&gt;Previously, all the functions returned some &lt;code&gt;IO&lt;/code&gt; wrapped value, and this makes tests complicated to setup.&lt;/p&gt;

&lt;p&gt;The first thing I did before setup tests was to split all core logic behind docs generation from the &lt;code&gt;IO&lt;/code&gt; related tasks.&lt;/p&gt;

&lt;p&gt;Posting the whole code here is a non-sense (~436 LOC), but the API for dhall-docs package ended up like this in summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cd"&gt;-- | The result of the doc-generator pure component&lt;/span&gt;
&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;GeneratedDocs&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;GeneratedDocs&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;DocsGenWarning&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;

&lt;span class="cm"&gt;{- `GeneratedDocs` is an instance of MonadWriter to make warning logging easier,
   omitted the instance declaration since it makes some noise in the post -}&lt;/span&gt;

&lt;span class="cm"&gt;{-| Generate all of the docs for a package. This function does all the `IO ()`
    related tasks to call `generateDocsPure`
-}&lt;/span&gt;
&lt;span class="n"&gt;generateDocs&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Path&lt;/span&gt; &lt;span class="kt"&gt;Abs&lt;/span&gt; &lt;span class="kt"&gt;Dir&lt;/span&gt; &lt;span class="c1"&gt;-- ^ Input directory&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Path&lt;/span&gt; &lt;span class="kt"&gt;Abs&lt;/span&gt; &lt;span class="kt"&gt;Dir&lt;/span&gt; &lt;span class="c1"&gt;-- ^ Link to be created to the generated documentation&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;         &lt;span class="c1"&gt;-- ^ Package name, used in some HTML titles&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;

&lt;span class="cm"&gt;{-| Generates all the documentation of dhall package in a pure way i.e.
    without an `IO` context. This lets you generate documentation from a list of
    dhall-files without saving them to the filesystem.

    If you want the `IO` version of this function, check `generateDocs`
-}&lt;/span&gt;
&lt;span class="n"&gt;generateDocsPure&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;                    &lt;span class="c1"&gt;-- ^ Package name&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="kt"&gt;Path&lt;/span&gt; &lt;span class="kt"&gt;Rel&lt;/span&gt; &lt;span class="kt"&gt;File&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="c1"&gt;-- ^ (Input file, contents)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;GeneratedDocs&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="kt"&gt;Path&lt;/span&gt; &lt;span class="kt"&gt;Rel&lt;/span&gt; &lt;span class="kt"&gt;File&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This introduced some cool benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pure code is easier to test.&lt;/li&gt;
&lt;li&gt;From my little Haskell experience, the less you are coupled with an &lt;code&gt;IO&lt;/code&gt; context the better.&lt;/li&gt;
&lt;li&gt;The code is cleaner than before.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to my mentors for pushing me into this direction!&lt;/p&gt;

&lt;h2&gt;
  
  
  Breadcrumbs generation
&lt;/h2&gt;

&lt;p&gt;The challenging part on breadcrumbs generation is to wire up the links to other super-folders correctly since they depend on the type of the HTML file you're generating.&lt;/p&gt;

&lt;p&gt;Let's take the following breadcrumb:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my / super / breadcrumb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The last breadcrumb component is never a link since it always refers to the current page you're looking at. If you're on an index page, the page where you'll be redirected will be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# "breadcrumb" is your current page
my                 / super           / breadcrumb
"../../index.html"   "../index.html"   no link 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;whereas if you were on a Dhall file page, it will render the link like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# "breadcrumb" is your current page
my                 / super           / breadcrumb     / file.dhall
"../../index.html"   "../index.html"   "./index.html"   no-link
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Get this right was cumbersome by using only lists, so I created my custom list-like ADT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cd"&gt;-- | ADT for handling bread crumbs. This is essentially a backward list&lt;/span&gt;
&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Breadcrumb&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Crumb&lt;/span&gt; &lt;span class="kt"&gt;Breadcrumb&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;EmptyCrumb&lt;/span&gt;
    &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;

&lt;span class="cm"&gt;{-| Convert a relative path to a `Breadcrumb`.

&amp;gt;&amp;gt;&amp;gt; relPathToBreadcrumb [reldir|a/b/c|]
Crumb (Crumb (Crumb EmptyCrumb "a") "b") "c"
&amp;gt;&amp;gt;&amp;gt; relPathToBreadcrumb [reldir|.|]
Crumb EmptyCrumb ""
&amp;gt;&amp;gt;&amp;gt; relPathToBreadcrumb [relfile|c/foo.baz|]
Crumb (Crumb EmptyCrumb "c") "foo.baz"
-}&lt;/span&gt;
&lt;span class="n"&gt;relPathToBreadcrumb&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Path&lt;/span&gt; &lt;span class="kt"&gt;Rel&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Breadcrumb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The reason why it's a backward list is to make it easier to generate the relative links backward while mapping these breadcrumbs to &lt;code&gt;Html ()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After adding this, we started noticing that the code was growing a lot and things start to complicate. We needed a way to ensure that adding a new feature doesn't break anything else. Oh yeah, we needed tests!&lt;/p&gt;

&lt;p&gt;(before digging into the test-setup section, I'll show you some screenshot of how the breadcrumbs look)&lt;/p&gt;

&lt;p&gt;On a Dhall's file documentation&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--78EuDH5C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1yil2let2yekf3m47kec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--78EuDH5C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1yil2let2yekf3m47kec.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On an index:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r7fC4mGC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bx4qvrdycahku362514d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r7fC4mGC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bx4qvrdycahku362514d.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Test-setup
&lt;/h2&gt;

&lt;p&gt;Currently, our Haskell API changes frequently on each PR, and testing each function in isolation will complicate things a little.&lt;/p&gt;

&lt;p&gt;Remember that the input of &lt;code&gt;dhall-docs&lt;/code&gt; is a list of dhall files with their relative paths, and the output is a list of generated HTML documents that represents the generated documentation.&lt;/p&gt;

&lt;p&gt;We want out test-setup to be easy to maintain and that adding new test cases is as easy as adding an input file and an &lt;em&gt;expected&lt;/em&gt; output file&lt;/p&gt;

&lt;p&gt;A golden-tests setup is really good for this! Golden tests are structured like this&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are two types of files:

&lt;ul&gt;
&lt;li&gt;Input files: The input of the function&lt;/li&gt;
&lt;li&gt;Output files: Are written by the function given an input file&lt;/li&gt;
&lt;li&gt;Golden files: The expected output of the function. The test-runner should compare them with the output files after execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may be wondering that this is no different as the usual test-setup like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;actual &amp;lt;- function(input)
shouldBeEqual(actual, expected)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;but when we are dealing with tests that involve accessing the file-system, this is a better approach.&lt;/p&gt;

&lt;p&gt;Almost all tests-setup in &lt;code&gt;dhall-haskell&lt;/code&gt; are written in &lt;code&gt;tasty&lt;/code&gt;, which has several sub-packages that can be seen as &lt;em&gt;plugins&lt;/em&gt;. For golden-tests, we decided to use &lt;code&gt;tasty-silver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The core of our test-setup is in the &lt;code&gt;goldenVsAction&lt;/code&gt; function from the &lt;code&gt;tasty-silver&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;goldenVsAction&lt;/span&gt;
  &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;TestName&lt;/span&gt; &lt;span class="c1"&gt;-- ^ test name&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FilePath&lt;/span&gt; &lt;span class="c1"&gt;-- ^ path to the «golden» file (the file that contains correct output)&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;-- ^ action that returns a text-like value.&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;T&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- ^ Converts a value to it's textual representation.&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;TestTree&lt;/span&gt; &lt;span class="c1"&gt;-- ^ the test verifies that the returned textual representation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Look that we don't use output files because they mess a little with the VCS. In this function, we mimic writing a file via &lt;em&gt;actions&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The test-runner includes a &lt;code&gt;--accept&lt;/code&gt; flag that updates or creates golden files in case of test-failures. This is handy to be used when we add a new feature that changes all outputs, and we want to update them in a single run; or when we add a new test-file to generate its corresponding golden file.&lt;/p&gt;

&lt;p&gt;The whole test-setup fits under 66 lines of code, and we probably won't have the need to edit it again in the future: If we want to write a test for a new feature or bug, we add the file in the test package directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before leaving
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! Keep in tune for my next posts!&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>dhall</category>
      <category>gsoc</category>
    </item>
    <item>
      <title>Type on index &amp; examples from assertions</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Wed, 08 Jul 2020 19:05:17 +0000</pubDate>
      <link>https://dev.to/german1608/type-on-index-examples-from-assertions-4kan</link>
      <guid>https://dev.to/german1608/type-on-index-examples-from-assertions-4kan</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hi there! Today I'm going to tell you some progress made in the project so far, specifically the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type of files on each index&lt;/li&gt;
&lt;li&gt;Examples from assertions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TL-DR
&lt;/h2&gt;

&lt;p&gt;If you just want to see the progress, check out here&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hydra.dhall-lang.org/build/64022/download/1/docs/" rel="noopener noreferrer"&gt;https://hydra.dhall-lang.org/build/64022/download/1/docs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Type of a dhall file
&lt;/h2&gt;

&lt;p&gt;Usually in typed languages like Dhall or Haskell, the type of any value is more useful than its name. You can get an insight into what a function does with just its type.&lt;/p&gt;

&lt;p&gt;In the case of Haskell, this fact is exploited a lot. There is a website similar to "google" that let you search functions that match a type that you defined: &lt;a href="http://hoogle.haskell.org/" rel="noopener noreferrer"&gt;http://hoogle.haskell.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In another project (&lt;a href="https://github.com/aitorres/firelink" rel="noopener noreferrer"&gt;firelink&lt;/a&gt;) that I was developing, there was a circumstance where I wanted to get the &lt;code&gt;Just&lt;/code&gt; values from a list of &lt;code&gt;Maybe&lt;/code&gt;s, something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I &lt;a href="https://hoogle.haskell.org/?hoogle=%5BMaybe+a%5D+-%3E+%5Ba%5D" rel="noopener noreferrer"&gt;"hoogled"&lt;/a&gt; the type and it showed me &lt;code&gt;catMaybes&lt;/code&gt;, which does exactly what I wanted to. Without looking up for the name, just the type.&lt;/p&gt;

&lt;p&gt;On Dhall, we have a similar urge: types are more meaningful than the name. So a cool feature that I add was showing the type of the expression on the index page.&lt;/p&gt;

&lt;p&gt;Type-checking a dhall expression is something that involves several steps. This can get cumbersome in this context and fact, we (my mentors and I) didn't want to do so (the whole algorithm is described &lt;a href="https://docs.dhall-lang.org/tutorials/Language-Tour.html#introduction" rel="noopener noreferrer"&gt;here&lt;/a&gt;). The way we extract the type from a dhall file is by analyzing the source code.&lt;/p&gt;

&lt;p&gt;The only kind of expressions that this feature supports are let-bindings, which in the internal AST representation are constructed using the following constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Let (Binding _ x _  Nothing  _ r) e ~ let x     = r in e&lt;/span&gt;
&lt;span class="c1"&gt;-- Let (Binding _ x _ (Just t ) _ r) e ~ let x : t = r in e&lt;/span&gt;
&lt;span class="kt"&gt;Let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Binding&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dhall also supports multiple-let bindings, to write code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="kr"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what we do is check if the last expression in the binding is a variable name, and traverse backward the list of bindings to get the desired one and finally its associated type (which may be absent).&lt;/p&gt;

&lt;p&gt;There is a slight modification to support referencing variables with their indexes, for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;True&lt;/span&gt;
&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Natural&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kr"&gt;in&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... will return &lt;code&gt;Natural&lt;/code&gt; as its type because it is the closes lexical binding, but if we change the last line to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;in&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it will return &lt;code&gt;Bool&lt;/code&gt;. The final code for that was the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- The `V` constructor is used to handle name references on&lt;/span&gt;
&lt;span class="c1"&gt;-- Dhall expressions, whereas&lt;/span&gt;
&lt;span class="n"&gt;extractTypeIfInSource&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;extractTypeIfInSource&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="kt"&gt;V&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;maybeNameInLet&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Binding&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exprType&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;
        &lt;span class="n"&gt;getLetBindingWithIndex&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;getLetBindingsWithName&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
    &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="n"&gt;exprType&lt;/span&gt;
    &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="c1"&gt;-- | For an expression of the form @let x0 = y0 let x1 = y1 ... in e@&lt;/span&gt;
    &lt;span class="c1"&gt;--   where @e@ is a variable, maybeNameInLet returns the variable name.&lt;/span&gt;
    &lt;span class="n"&gt;maybeNameInLet&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Var&lt;/span&gt;
    &lt;span class="n"&gt;maybeNameInLet&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Var&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;V&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="n"&gt;maybeNameInLet&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Let&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maybeNameInLet&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="n"&gt;maybeNameInLet&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;

    &lt;span class="n"&gt;getLetBindingsWithName&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Binding&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;getLetBindingsWithName&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;bindName&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bindings&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;
        &lt;span class="kr"&gt;where&lt;/span&gt;
        &lt;span class="n"&gt;bindName&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Binding&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;


    &lt;span class="n"&gt;getLetBindingWithIndex&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Binding&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Binding&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;getLetBindingWithIndex&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;bs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;bs&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
            &lt;span class="kt"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
            &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;binding&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I get this right I was kind of excited because it was the first time in my life where I used &lt;code&gt;Maybe&lt;/code&gt; as a Monad. The code works (thanks tests!) and takes into account the cases with variable indexing.&lt;/p&gt;

&lt;p&gt;Here you can see a preview of how it looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkd8zwen82k6b292o68oz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkd8zwen82k6b292o68oz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool right? 😎&lt;/p&gt;

&lt;p&gt;Let's get to the next feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples from assertions
&lt;/h3&gt;

&lt;p&gt;Dhall has a nice feature named &lt;em&gt;assertions&lt;/em&gt;. This lets you add unit tests to your files and the type-checking phase will fail if any of these assertions fail.&lt;/p&gt;

&lt;p&gt;We wanted a way to get examples of using a Dhall file expression, and the best way to do so was extracting them from the assertions body.&lt;/p&gt;

&lt;p&gt;For instance, if we have something like this in a Dhall file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;example0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;e0&lt;/span&gt;
&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;example1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;on the generated documentation you will look &lt;code&gt;e0&lt;/code&gt; and &lt;code&gt;e1&lt;/code&gt; as code examples.&lt;/p&gt;

&lt;p&gt;The code manipulates the syntax-tree as the &lt;code&gt;extractTypeFromSource&lt;/code&gt; does, but it's more compact and easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;examplesFromAssertions&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;examplesFromAssertions&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapMaybe&lt;/span&gt; &lt;span class="n"&gt;fromAssertion&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;
    &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bindings&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;

    &lt;span class="n"&gt;fromAssertion&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fromAssertion&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Assert&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="n"&gt;fromAssertion&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a preview of it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkszd5limmm8e6mmnqdla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkszd5limmm8e6mmnqdla.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Neat 💥&lt;/p&gt;

&lt;h2&gt;
  
  
  If you read this...
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! Keep in tune for future posts 😊.&lt;/p&gt;

&lt;p&gt;If you liked this, please comment or react in the post ❤️&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Document generation &amp; Rendered Source Code</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Sun, 28 Jun 2020 22:51:39 +0000</pubDate>
      <link>https://dev.to/german1608/document-generation-rendered-source-code-10cb</link>
      <guid>https://dev.to/german1608/document-generation-rendered-source-code-10cb</guid>
      <description>&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;If you only want to see my current progress, you can visit this website to see it &lt;a href="https://hydra.dhall-lang.org/build/63538/download/1/docs/"&gt;https://hydra.dhall-lang.org/build/63538/download/1/docs/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Motivation
&lt;/h1&gt;

&lt;p&gt;What is a &lt;em&gt;document generator&lt;/em&gt;? If you're familiar with other programming languages such as Java or Haskell, for example, you may know of tools that analyze your source code, extract useful information in your &lt;a href="https://en.wikipedia.org/wiki/Comment_(computer_programming)"&gt;comments&lt;/a&gt; and display them in a a markup language such as HTML, for instance.&lt;/p&gt;

&lt;p&gt;In haskell, that tool is &lt;a href="https://www.haskell.org/haddock/"&gt;haddock&lt;/a&gt;. It analyzes your source code, searching for comment annotations on your data-types and functions, to report them in a nice way using HTML.&lt;/p&gt;

&lt;p&gt;For instance, the following function declaration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cd"&gt;-- | Function description&lt;/span&gt;
&lt;span class="n"&gt;haddockExample&lt;/span&gt;
  &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;-- ^ input description&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="c1"&gt;-- ^ output description&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;it will render something like this on the generated HTML:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8t0X8JDi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q0h3bn8fn244hvzykwku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8t0X8JDi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q0h3bn8fn244hvzykwku.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The generated HTML can be then uploaded to any host to serve them. This is useful if you're a package maintainer to let your consumers know how to use your packages.&lt;/p&gt;

&lt;p&gt;The main goal of this #GSoC project is to build a similar tool for the &lt;a href="https://dhall-lang.org"&gt;Dhall&lt;/a&gt; configuration language. I set some milestones for the project, and this post will focus on the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate some readable with a nice UI/UX from a dhall package. A Dhall package is essentially (at this moment) a folder with several Dhall files, ending with the &lt;code&gt;.dhall&lt;/code&gt; extension.&lt;/li&gt;
&lt;li&gt;Add rendered source code (first iteration). Haddock does it. For each haskell module, it will create:

&lt;ul&gt;
&lt;li&gt;The HTML documentation&lt;/li&gt;
&lt;li&gt;A HTML rendered source code, similar to &lt;a href="https://hackage.haskell.org/package/dhall-1.33.1/docs/src/Dhall.Core.html"&gt;this&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Documentation generator
&lt;/h1&gt;

&lt;p&gt;At this moment, I developed the &lt;code&gt;dhall-docs&lt;/code&gt; executable. That takes the following flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--input&lt;/code&gt;, which is a relative or absolute path to the Dhall package.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--output-link&lt;/code&gt;, which is a symlink (defaulting to &lt;code&gt;./docs&lt;/code&gt;) to the generated documentation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--package-name&lt;/code&gt;, which is the actual package-name used in HTML titles and in the place where generated documentation are &lt;em&gt;actually&lt;/em&gt; saved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool will traverse the whole &lt;code&gt;--input&lt;/code&gt; directory in a recursive way, searching for all the files that ends in &lt;code&gt;.dhall&lt;/code&gt; and parse them. If a dhall file fails to parse as a Dhall expression, it won't be included.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure of the generated documentation
&lt;/h2&gt;

&lt;p&gt;On each directory on the generated documentation, an &lt;code&gt;index.html&lt;/code&gt; file is generated listing the subpackages (the directories in it) and the exported dhall files in that level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0rTPCYgu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ugcrskmfe5y3ejp04us2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0rTPCYgu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ugcrskmfe5y3ejp04us2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we visit a &lt;em&gt;.dhall&lt;/em&gt; file, we can see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JMCUeWuo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7h7vtg2u37e8o9um9fuq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JMCUeWuo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7h7vtg2u37e8o9um9fuq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following is the actual source code that the tool took as its part of its input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cm"&gt;{-
`subtract m n` computes `n - m`, truncating to `0` if `m &amp;gt; n`
-}&lt;/span&gt;
&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;subtract&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Natural&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="kt"&gt;Natural&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="kt"&gt;Natural&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Natural&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;subtract&lt;/span&gt;

&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;example0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subtract&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="err"&gt;≡&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;example1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subtract&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;≡&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;example2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subtract&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;≡&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;property0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;λ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Natural&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subtract&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="err"&gt;≡&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;

&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;property1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;λ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Natural&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subtract&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="err"&gt;≡&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;property2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;λ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Natural&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subtract&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="err"&gt;≡&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="kr"&gt;in&lt;/span&gt;  &lt;span class="n"&gt;subtract&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you would notice, the &lt;code&gt;Documentation&lt;/code&gt; header on the generated HTML corresponds to the &lt;em&gt;Header&lt;/em&gt; comment, and the actual source code is the rest of the file. The header is written in Markdown, &lt;code&gt;dhall-docs&lt;/code&gt; uses &lt;a href="https://hackage.haskell.org/package/mmark"&gt;&lt;code&gt;mmark&lt;/code&gt;&lt;/a&gt; as markdown parser and preprocessor.&lt;/p&gt;

&lt;p&gt;This is the first iteration of the work, I have plans on expanding the places where annotation comments can go, &lt;br&gt;
like record type labels, for example.&lt;/p&gt;

&lt;p&gt;Here is the list of PRs involved on this task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1833"&gt;dhall-haskell#1833&lt;/a&gt; introduced the repository skeleton&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1845"&gt;dhall-haskell#1845&lt;/a&gt; first attempt to generate this documentation without any css, parsing the header without using a markdown pre-processor.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1848"&gt;dhall-haskell#1848&lt;/a&gt; improved the css rules&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1863"&gt;dhall-haskell#1863&lt;/a&gt; parsed the header markdown contents and rendered them on the html page&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1871"&gt;dhall-haskell#1871&lt;/a&gt; added a small ci/cd configuration to generate sample documentation. you can see it &lt;a href="https://hydra.dhall-lang.org/build/63538/download/1/docs/index.html"&gt;here&lt;/a&gt;. This was my hardest task since I didn't knew any of nix, feels good to actually have accomplish it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1876"&gt;dhall-haskell#1876&lt;/a&gt; stored the generated documentation at &lt;code&gt;$XDG_DATA_HOME/dhall-docs&lt;/code&gt; following the &lt;a href="https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html"&gt;XDG&lt;/a&gt; specification. Documentation is stored at &lt;code&gt;$XDG_DATA_HOME/dhall-docs/${SHA256_OF_DOCS}-${PACKAGE-NAME}&lt;/code&gt; this makes it content-addressable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of the work was really ad-hoc, so I won't add any implementation details: you can see them on the PRs. Next section was way more interesting to implement, so please keep reading :)&lt;/p&gt;
&lt;h1&gt;
  
  
  Rendered Source Code (first iteration)
&lt;/h1&gt;

&lt;p&gt;On the previous section I showed up a first iteration on rendered source code. There were several ways of doing this task, but the thing that I was &lt;em&gt;almost&lt;/em&gt; about to start to do was to traverse the Dhall AST, generating &lt;code&gt;Html ()&lt;/code&gt;. In FP terms, I should create a catamorphism. In non-FP terms, I should create a mapper.&lt;/p&gt;

&lt;p&gt;But this was going to involve a lot of lines of code, and actually some repetition of what the &lt;code&gt;Dhall.Pretty&lt;/code&gt; module of the &lt;code&gt;dhall&lt;/code&gt; package does i.e. define formatting rules for the AST elements and tokens.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Dhall.Pretty&lt;/code&gt; module used under the hood the &lt;a href="https://hackage.haskell.org/package/prettyprinter-1.6.2"&gt;&lt;code&gt;prettyprinter&lt;/code&gt;&lt;/a&gt;, its core consists of the following functions and ADT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Ann&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Keyword&lt;/span&gt;     &lt;span class="c1"&gt;-- ^ Used for syntactic keywords&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Syntax&lt;/span&gt;      &lt;span class="c1"&gt;-- ^ Syntax punctuation such as commas, parenthesis, and braces&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Label&lt;/span&gt;       &lt;span class="c1"&gt;-- ^ Record labels&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Literal&lt;/span&gt;     &lt;span class="c1"&gt;-- ^ Literals such as integers and strings&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Builtin&lt;/span&gt;     &lt;span class="c1"&gt;-- ^ Builtin types and values&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Operator&lt;/span&gt;    &lt;span class="c1"&gt;-- ^ Operators&lt;/span&gt;
  &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;

&lt;span class="c1"&gt;-- Create a `Doc Ann` from a dhall expression&lt;/span&gt;
&lt;span class="c1"&gt;-- annotating elements using our syntatic rules&lt;/span&gt;
&lt;span class="n"&gt;prettyExpr&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Pretty&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Doc&lt;/span&gt; &lt;span class="kt"&gt;Ann&lt;/span&gt;

&lt;span class="c1"&gt;-- SimpleDocStream can be later rendered as `Text` on&lt;/span&gt;
&lt;span class="c1"&gt;-- a terminal&lt;/span&gt;
&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Doc&lt;/span&gt; &lt;span class="n"&gt;ann&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;SimpleDocStream&lt;/span&gt; &lt;span class="n"&gt;ann&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This module contained basically all of what I have to do, and repeating code is bad! The &lt;a href="https://hackage.haskell.org/package/prettyprinter-1.6.2"&gt;&lt;code&gt;prettyprinter&lt;/code&gt;&lt;/a&gt; says on its package description:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A prettyprinter/text rendering engine. Easy to use, well-documented, ANSI terminal backend exists, &lt;strong&gt;HTML backend is trivial to implement&lt;/strong&gt;, no name clashes, Text-based, extensible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;so I thought: &lt;em&gt;"man, there should be a way to generate &lt;code&gt;Html ()&lt;/code&gt; from a dhall expression using this module"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And there &lt;em&gt;was&lt;/em&gt; a way. On the package documentation, they recommend using &lt;code&gt;SimpleDocTree&lt;/code&gt; instead of &lt;code&gt;SimpleDocStream&lt;/code&gt; to render HTML-like output, and the package itself exports an utility to do the conversion: &lt;code&gt;treeForm&lt;/code&gt;. Traversing the &lt;code&gt;SimpleDocTree&lt;/code&gt; ADT made all this work possible in the following function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Lucid&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Dhall.Pretty&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Ann&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Data.Text.Prettyprint.Doc.Render.Util.SimpleDocTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Pretty&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Dhall.Pretty&lt;/span&gt;

&lt;span class="n"&gt;exprToHtml&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt; &lt;span class="kt"&gt;Src&lt;/span&gt; &lt;span class="kt"&gt;Import&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;exprToHtml&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;renderTree&lt;/span&gt; &lt;span class="n"&gt;prettyTree&lt;/span&gt;
  &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;prettyTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;treeForm&lt;/span&gt;
        &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Dhall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;
        &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Dhall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prettyExpr&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;

    &lt;span class="n"&gt;textSpaces&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;
    &lt;span class="n"&gt;textSpaces&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replicate&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;renderTree&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;SimpleDocTree&lt;/span&gt; &lt;span class="kt"&gt;Ann&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;renderTree&lt;/span&gt; &lt;span class="n"&gt;sds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;sds&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;STEmpty&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
        &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;STChar&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;toHtml&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
        &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;STText&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;toHtml&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
        &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;STLine&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;br_&lt;/span&gt; &lt;span class="kt"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;toHtml&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;textSpaces&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;STAnn&lt;/span&gt; &lt;span class="n"&gt;ann&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;encloseInTagFor&lt;/span&gt; &lt;span class="n"&gt;ann&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderTree&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kt"&gt;Pretty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;STConcat&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foldMap&lt;/span&gt; &lt;span class="n"&gt;renderTree&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt;

    &lt;span class="n"&gt;encloseInTagFor&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Ann&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;encloseInTagFor&lt;/span&gt; &lt;span class="n"&gt;ann&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;span_&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;class_&lt;/span&gt; &lt;span class="n"&gt;classForAnn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="kr"&gt;where&lt;/span&gt;
        &lt;span class="n"&gt;classForAnn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dhall-"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;ann&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
            &lt;span class="kt"&gt;Keyword&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"keyword"&lt;/span&gt;
            &lt;span class="c1"&gt;-- ommited for brevity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is similar to the first option: transform the Dhall AST (&lt;code&gt;Expr s e&lt;/code&gt;) to &lt;code&gt;Html ()&lt;/code&gt;, the difference is that we don't have to worry about the types of syntactical elements: that logic can be kept on the &lt;code&gt;Dhall.Pretty&lt;/code&gt; module, and this function only creates the &lt;code&gt;Html ()&lt;/code&gt; from it.&lt;/p&gt;

&lt;p&gt;The PR that introduced that change is &lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1892"&gt;dhall-haskell#1892&lt;/a&gt;, and we can see how many additions/deletions that change involved:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---xA--SbO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m5afklrqctstpk0aood4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---xA--SbO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m5afklrqctstpk0aood4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Neat! A lot of value in less than 160 lines of code.&lt;/p&gt;

&lt;h1&gt;
  
  
  The things I learnt along the way
&lt;/h1&gt;

&lt;p&gt;Of course, I've improved my haskell, specifically the package ecosystem. One of the things that overwhelmed (and sometimes annoyed me) is how package versions are resolved, and since we have to ensure our project works on several GHC versions with several package versions, we have to be really sure about the version of a package that we are adding.&lt;/p&gt;

&lt;p&gt;This was difficult on the first two weeks, since I had to do some little research about packages to render HTML and parse markdown, and fight against the ci/cd pipeline when a version error occurred.&lt;/p&gt;

&lt;p&gt;Thankfully, now I understand better how it works, and in the future of the project I don't think I'll add more packages, but now I'm sure how to tackle that kind of issues.&lt;/p&gt;

&lt;p&gt;Another thing that I've learned a little on the project was &lt;a href="https://nixos.org/"&gt;Nix&lt;/a&gt;. In short words, its a functional package manager. Fun fact: I see that a lot of people that enters the functional programming world tends to use only tools that uses that paradigm. Everytime I searched something about &lt;a href="https://nixos.org/"&gt;Nix&lt;/a&gt;, it was using a &lt;a href="https://haskell.org"&gt;haskell&lt;/a&gt; project.&lt;/p&gt;

&lt;h1&gt;
  
  
  If you made it this far
&lt;/h1&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>dhall</category>
      <category>gsoc</category>
    </item>
    <item>
      <title>Prelude</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Wed, 10 Jun 2020 23:33:58 +0000</pubDate>
      <link>https://dev.to/german1608/prelude-48a1</link>
      <guid>https://dev.to/german1608/prelude-48a1</guid>
      <description>&lt;h1&gt;
  
  
  Prelude
&lt;/h1&gt;

&lt;h2&gt;
  
  
  GSoC application
&lt;/h2&gt;

&lt;p&gt;First things first: I really like &lt;a href="https://www.haskell.org/"&gt;Haskell&lt;/a&gt;. I started learning the language a year ago~ on university courses about compiler design and I wanted more real-life experience with the language.&lt;/p&gt;

&lt;p&gt;I heard of GSoC from a friend last year and decided to apply. Of course, I wanted to go with a haskell project. The list of &lt;a href="https://summer.haskell.org/ideas.html"&gt;project ideas&lt;/a&gt; provided by the haskell commitee looked really challenging at the begginning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The hard ideas were really hard not only because it required an advanced understanding on the language but also deeper understanding of hard CS subjects and contributing on some of the biggest projects of the whole haskell ecosystem like &lt;a href="https://hackage.haskell.org/package/QuickCheck"&gt;QuickCheck&lt;/a&gt;, &lt;a href="https://github.com/hasktorch/hasktorch"&gt;hasktorch&lt;/a&gt; and even the compiler itself &lt;a href="https://github.com/ghc/ghc"&gt;ghc&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;There were some ideas on project that I didn't knew and didn't understand what its purpose was&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After reading digesting the whole list, I decided to look after the &lt;a href="https://summer.haskell.org/ideas.html#dhall-documentation-generator"&gt;Dhall Documentation Generator&lt;/a&gt; project. I didn't knew anything about dhall before reading it on that list, but I took a look at the language and decided to give it a try and write my proposal. After contacting the mentors, who were (and are) really friendly and brainstorming a little about the goal of the project, I submited my proposal to GSoC.&lt;/p&gt;

&lt;h2&gt;
  
  
  I got selected!
&lt;/h2&gt;

&lt;p&gt;On May 4 news arrived to my email: my proposal was selected! Immediately, my mentors contacted me congratulating me and they give me an onboard with the project details.&lt;/p&gt;

&lt;p&gt;I cloned the &lt;a href="https://github.com/dhall-lang/dhall-haskell"&gt;repository&lt;/a&gt; where I'm going to be developing my project, and try to read and understand the existing code.&lt;/p&gt;

&lt;p&gt;The repository is really huge and well documented, the good thing about haskell is that by reading a function's type definition you get an idea of what the function actually does.&lt;/p&gt;

&lt;p&gt;But that wasn't enough to get a deep understanding of the project. The first thing I like to do before starting working on a new project either on an academic or a work context is to take some small existing issues and solve them. I looked at the issue tracker of the repository to see what I was able to do without a deep understangind of the project and submitted (and successfully merged 🎉) the following PRs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1788"&gt;#1788&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1793"&gt;#1793&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1799"&gt;#1799&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1801"&gt;#1801&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1806"&gt;#1806&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1833"&gt;#1833&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dhall-lang/dhall-haskell/pull/1843"&gt;#1843&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;After investing enough time in understanding not just the haskell code but also how the project is structured, I decided to start earlier my project. I hope that project goes well in its development.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>gsoc</category>
      <category>dhall</category>
    </item>
    <item>
      <title>GSoC 2020: Dhall Documentation Generator</title>
      <dc:creator>German Robayo</dc:creator>
      <pubDate>Wed, 10 Jun 2020 23:30:49 +0000</pubDate>
      <link>https://dev.to/german1608/gsoc-2020-dhall-documentation-generator-37l</link>
      <guid>https://dev.to/german1608/gsoc-2020-dhall-documentation-generator-37l</guid>
      <description>&lt;p&gt;Hi everyone!&lt;/p&gt;

&lt;p&gt;This is my very first post here and I'd like to start with something really great that happened recently.&lt;/p&gt;

&lt;p&gt;I've submitted a proposal for a GSoC and got accepted! My concrete proposal summary can be found &lt;a href="https://summerofcode.withgoogle.com/projects/#5366051979657216"&gt;here&lt;/a&gt;. In summary, I'm going to develop a Dhall Documentation Generator as this post title suggests. The milestones of this project are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate a simple HTML folder with the documentation of a dhall package;&lt;/li&gt;
&lt;li&gt;Render the dhall source code as haddock (the documentation generator for haskell) does;&lt;/li&gt;
&lt;li&gt;Jump to definition on both documentation and source code;&lt;/li&gt;
&lt;li&gt;Type on hover on both documentation and source code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll try to write several posts each time I accomplish a milestone of a project, so I might end up writing at least 4 posts. This post will contain a "table of contents" for all the development of the project.&lt;/p&gt;

&lt;p&gt;If you don't know what the &lt;code&gt;dhall&lt;/code&gt; configuration language is, a good place to learn is its &lt;a href="https://dhall-lang.org"&gt;website&lt;/a&gt;&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>gsoc</category>
      <category>dhall</category>
    </item>
  </channel>
</rss>
