<?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: webbureaucrat</title>
    <description>The latest articles on DEV Community by webbureaucrat (@webbureaucrat).</description>
    <link>https://dev.to/webbureaucrat</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%2F142698%2F5b2af2bd-bcca-4fe1-a8c5-cc8f8462f166.png</url>
      <title>DEV Community: webbureaucrat</title>
      <link>https://dev.to/webbureaucrat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/webbureaucrat"/>
    <language>en</language>
    <item>
      <title>Finding a Successful Build of NodeJS in Nixpkgs</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Thu, 31 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/finding-a-successful-build-of-nodejs-in-nixpkgs-5je</link>
      <guid>https://dev.to/webbureaucrat/finding-a-successful-build-of-nodejs-in-nixpkgs-5je</guid>
      <description>&lt;p&gt;My latest irritation has been using NodeJS with Nix. Unfortunately, I've had a few unfortunate draws pulling versions of nixpkgs that build &lt;strong&gt;the entire NodeJS V8 runtime from source&lt;/strong&gt;. It's been a pain and I would like to not go through that any more, so I am documenting the steps to avoid it.&lt;/p&gt;

&lt;h3&gt;
  
  
  It's not you; it's Node.
&lt;/h3&gt;

&lt;p&gt;If you find yourself building NodeJS from source on nix, you can console yourself that at least &lt;em&gt;you&lt;/em&gt; didn't really do anything wrong--this is an issue with the NodeJS packages being very flaky on Hydra these days. The builds are often failing when nixpkgs gets built, and that failure gets passed onto you.&lt;/p&gt;

&lt;p&gt;So the goal is to find a version of nixpkgs that has the version of NodeJS you want &lt;em&gt;and&lt;/em&gt; successfully built that version in Hydra.&lt;/p&gt;

&lt;p&gt;Let's begin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps to finding a successfully pre-built NodeJS version from Nix's Hydra
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Identify the NodeJS version you want to use using &lt;a href="https://search.nixos.org/packages?channel=25.05&amp;amp;from=0&amp;amp;size=50&amp;amp;sort=relevance&amp;amp;type=packages&amp;amp;query=nodejs" rel="noopener noreferrer"&gt;the nixpkgs search site&lt;/a&gt;. For this example, I will be using &lt;code&gt;nodejs_24&lt;/code&gt; because it is the most recent version of NodeJS available at the time of this article.&lt;/li&gt;
&lt;li&gt;Identify your system platform by running
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nix-instantiate --eval --expr 'builtins.currentSystem'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this example, I will be using my own system, &lt;code&gt;"x86_64-linux"&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search for your NodeJS package on &lt;a href="https://hydra.nixos.org/" rel="noopener noreferrer"&gt;Hydra&lt;/a&gt;. For example, &lt;a href="https://hydra.nixos.org/search?query=nodejs_24" rel="noopener noreferrer"&gt;these are my search results&lt;/a&gt; when I search for "nodejs_24".&lt;/li&gt;
&lt;li&gt;Locate the proper job in the search results to see the builds for that job.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And now we can see the problem. At the time of this article, I can see that the nodejs_24 package is failing to build with alarming regularity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6eglh363m1zr0iyckwe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6eglh363m1zr0iyckwe.png" alt="A screencap of the list of recent Hydra builds, showing as many failures as successes" width="663" height="872"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can click on one of these succeeding builds and then along the top bar click on "Inputs". Now we can see the revision we need to select for our &lt;code&gt;nixpkgs&lt;/code&gt; property in our Nix expression.&lt;/p&gt;

&lt;p&gt;And we're done. I hope this article saves someone some searching, and I hope NodeJS gets a little more reliable. Thank you for reading.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nix</category>
      <category>node</category>
    </item>
    <item>
      <title>Building a Directory with `buildNpmPackage` in a Nix Derivation</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Sun, 09 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/building-a-directory-with-buildnpmpackage-in-a-nix-derivation-4hj4</link>
      <guid>https://dev.to/webbureaucrat/building-a-directory-with-buildnpmpackage-in-a-nix-derivation-4hj4</guid>
      <description>&lt;p&gt;Candidly, I'm very surprised it seems like no one has written this article yet, but I looked and it seems like no one has. The question I set out to answer is how to use a Nix derivation to build an npm package where the build product is not a single &lt;code&gt;"bin"&lt;/code&gt; executable file but rather a directory.&lt;/p&gt;

&lt;p&gt;Surely, this is a wildly common use cases in JavaScript, right? People compile TypeScript projects into directories all the time. (I prefer ReScript, but it's much the same.) Surely, not &lt;em&gt;everyone&lt;/em&gt; uses a script bundler, right? (Please don't disillusion me!)&lt;/p&gt;

&lt;p&gt;But I had more trouble with this than I expected. Fortunately, the Nix community is excellent, and &lt;a href="https://tilde.zone/@BryanBennett" rel="noopener noreferrer"&gt;@BryanBennett@tilde.zone&lt;/a&gt; on Mastodon &lt;a href="https://tilde.zone/@BryanBennett/114089526768487050" rel="noopener noreferrer"&gt;gave me the answer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For my setup, I'm building a &lt;em&gt;public/&lt;/em&gt; directory using an npm &lt;code&gt;"build"&lt;/code&gt; script set to &lt;code&gt;npx eleventy&lt;/code&gt;. This builds the static website.&lt;/p&gt;

&lt;p&gt;This is my derivative:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;mysite.nix&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;buildNpmPackage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;fileset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;sourceFiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;gitTracked&lt;/span&gt; &lt;span class="sx"&gt;./.&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt;
&lt;span class="nv"&gt;buildNpmPackage&lt;/span&gt; &lt;span class="kr"&gt;rec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;npmDepsHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sha256-+4lLBQ+UQ2XT0wwE6jADxG1UNZjLkQCLvvN1SdiUwZY="&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;pname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mysite"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;toSource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;./.&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;fileset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;sourceFiles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nv"&gt;postInstall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;cp -rv public/ $out&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.0.1"&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;The key here of course is the &lt;code&gt;postInstall&lt;/code&gt; script. The folder is there for us and we just have to go get it.&lt;/p&gt;

&lt;p&gt;(For completeness, if you're a beginner wondering how I got the &lt;code&gt;npmDepsHash&lt;/code&gt;, a good trick is just to leave the string empty so that the error message you get tells you what the string should be. The rest of this should look at least somewhat intuitive even if the Nix syntax terrifies you as much as it does me.)&lt;/p&gt;

&lt;p&gt;There's no magic in the &lt;em&gt;default.nix&lt;/em&gt;, here. Just pass in some packages and reference &lt;em&gt;mysite.nix&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;default.nix&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="c"&gt;# nixpkgs-24.11-darwin&lt;/span&gt;
  &lt;span class="c"&gt;# 2025-03-01&lt;/span&gt;
  &lt;span class="nv"&gt;nixpkgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;fetchTarball&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/NixOS/nixpkgs/archive/26a98b6560fe0526b324d76619ffc55e61b4625e.tar.gz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;pkgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="nv"&gt;overlays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;mysite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;callPackage&lt;/span&gt; &lt;span class="sx"&gt;./mysite.nix&lt;/span&gt; &lt;span class="p"&gt;{&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;And that's really all there is to it! Nix is often criticized for not having good documentation, so I figure every example of someone doing &lt;em&gt;something&lt;/em&gt; in Nix is bound to help the community a little.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>npm</category>
      <category>nix</category>
    </item>
    <item>
      <title>The Ten Commandments of Writing Programming Tutorials</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Fri, 21 Feb 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/the-ten-commandments-of-writing-programming-tutorials-31a3</link>
      <guid>https://dev.to/webbureaucrat/the-ten-commandments-of-writing-programming-tutorials-31a3</guid>
      <description>&lt;p&gt;Writing programming tutorials has made me better appreciate the pitfalls of writing. It's also made me that much more aware of badly written tutorials. Whereas before I might have just called myself stupid for not understanding something, I can now clearly see what the writer did wrong and how the information could have been presented better. Anyway, I'm tired of reading badly written tutorials and hope to start better conversations about tutorials, so, without further ado and in no particular order: the Decalogue:&lt;/p&gt;

&lt;h3&gt;
  
  
  Name things descriptively.
&lt;/h3&gt;

&lt;p&gt;It shouldn't come as a shock that the things that are good practices in writing production code are good practices in writing tutorial code, but too often I see &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; used as placeholders.&lt;/p&gt;

&lt;p&gt;Here's the thing: the whole reason people read tutorials is because they don't know how to do something themselves. If they had a pretty good idea what you were going to say, they wouldn't have bothered. This is what separates tutorial code from production code. This is why readability is so important.&lt;/p&gt;

&lt;p&gt;Now, it also doesn't come as a shock that naming things is hard, and it's especially hard in generalized articles that can be applied to a lot of different contexts. My advice is to pick an example context, so rather than calling your classes &lt;code&gt;SuperClass&lt;/code&gt; and &lt;code&gt;SubClass&lt;/code&gt;, for example, use&lt;code&gt;Animal&lt;/code&gt; and &lt;code&gt;Dog&lt;/code&gt;. Or even better, make a generalized &lt;em&gt;and&lt;/em&gt; specific implementation so your readers can grok the concept as well as how it is applied in the real world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Annotate types always.
&lt;/h3&gt;

&lt;p&gt;Example code is not the place to show off how smart your type inferencing system is. You should assume the person reading your writing isn't familiar with the libraries you're using, and that means they're going to have to look up all the types, so it's going to be a lot easier for your reader to grok your code if you go ahead and put your types inline. Most importantly, your reader isn't reading your code in an IDE; they're reading it on a webpage, so they can't just mouse over your object to see the type definition.&lt;/p&gt;

&lt;p&gt;Now, I hear you: it's true that not all languages support type annotations, but that doesn't make them unimportant. You can still annotate types in comments. That may not be an idiomatic way to use comments in a given language, and that's okay! Tutorial code doesn't have to be strictly idiomatic. It's more important to be skimmable to a beginner than idiomatic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep code in a working state.
&lt;/h3&gt;

&lt;p&gt;This rule can be bent a little if done thoughtfully. If there's some specific common pitfall you want the reader to see, it's okay to briefly show what's going to cause an error (although the case could be made that that should usually be broken out into its own article).&lt;/p&gt;

&lt;p&gt;What you should avoid, though, is something like "Start with a main function that calls these three functions, and then let's spend the next several pages implementing those three functions." If you're not yet ready to write the main function, don't confuse readers by having them write it.&lt;/p&gt;

&lt;p&gt;Instead, whenever possible, keep code in a state that compiles and, if possible, runs. That way, the reader always knows when they're on the right track and when they've gone astray.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoid summarizing code.
&lt;/h3&gt;

&lt;p&gt;Writing code snippets can be tempting, but, whenever possible, include entire code files instead of snippets unless what you're showing is completely trivial.&lt;/p&gt;

&lt;p&gt;I do understand the temptation. It's easy to think, for example, that the reader will be annoyed if they have to scroll past all the imports and boilerplate to see what you're trying to show, but think how much worse the reverse is: if there's something in the imports or boilerplate that they feel like they'd like to see, it's not just a matter of a little extra scrolling--they're stuck. There's no way around.&lt;/p&gt;

&lt;p&gt;If you do like to summarize code or show just one snippet at a time, there's a good solution: summarize code in the article, but include a link to a fully-functioning repository. That way, the user can see how all the parts fully fit together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Highlight syntax.
&lt;/h3&gt;

&lt;p&gt;Did you know implementations of markdown usually support highlighting syntax? You do now. Simply enclose your code in three backticks and include the language annotation next to the first set like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```typescript 
function thisHas(syntax: Highlighting) { } 
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please don't make anyone read code without sytax highlighting!&lt;/p&gt;

&lt;h3&gt;
  
  
  Write descriptive headings.
&lt;/h3&gt;

&lt;p&gt;Descriptive headings contribute greatly to search engine optimization. You owe it to yourself, your readers, and those hard-working web crawlers to put some thought into how you want your headings to read.&lt;/p&gt;

&lt;p&gt;It's not a bad idea to use your headings to reiterate some contextualizing information like the language or tech stack your using or the problem you're trying to solve. For example, instead of, "Recursive queries," try "Recursive T-SQL queries with Common Table Expressions (CTEs) in SQL Server." The latter is a mouthful and maybe a little redundant, but the extra search keywords will help your readers find you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use images where appropriate.
&lt;/h3&gt;

&lt;p&gt;Rule of thumb: if you're talking about menus, go ahead and include a screencap of the menu. In particular, I am thinking of .NET development in Visual Studio, which is famously menu-driven development.&lt;/p&gt;

&lt;p&gt;The reverse is just as important: &lt;em&gt;never&lt;/em&gt; use images to display code. To do so is inaccessible to screenreader users and just plain obnoxious to everyone else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distinguish between compiler and runtime errors.
&lt;/h3&gt;

&lt;p&gt;"Compile and run" feels so natural in a lot of languages. Lots of editors have a "Build &amp;amp; Run" button and lots of CLI tools have some equivalent, and this is great for day-to-day editing, but I recommend avoiding using it to demonstrate compiler errors. For example, don't advise the user to &lt;code&gt;cargo run&lt;/code&gt; a codebase where they're expected to get a compilation error. Tell them to &lt;code&gt;cargo check&lt;/code&gt;the code instead.&lt;/p&gt;

&lt;p&gt;I say this because lots of beginners struggle with the difference between compile-time and runtime errors. Getting in the habit of using a separate compilation step will help them get over the hurdle faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Include the full message when describing errors.
&lt;/h3&gt;

&lt;p&gt;A lot of writers will just say, "X will produce a runtime error" or "Y will generate a compiler error." I highly encourage you to specify the exact wording of the error generated--maybe even a partial stack trace. Doing so will help the reader understand the error without having to reproduce it themselves, and it has the added benefit of helping your readers find your article through search engines because users are likely to be searching for specific errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Import everything explicitly.
&lt;/h3&gt;

&lt;p&gt;Every language I'm aware of has some form of&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Python&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;my_module&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Rust&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;my_module&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and depending on your preferences and the conventions of your language, you may do something like that all the time. (I do not.)&lt;/p&gt;

&lt;p&gt;But remember, in your day to day you have access to an IDE where you can mouse over things to tell where they came from and flip to a construct's definition with a couple of keystrokes. Your readers don't have that, unless you really expect them to &lt;em&gt;have to&lt;/em&gt; follow along with every line in order to be able to use your tutorial.&lt;/p&gt;

&lt;p&gt;So even though it makes for a few extra lines and a little extra scrolling, make all your imports explicit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Epilogue
&lt;/h3&gt;

&lt;p&gt;I know I'm bloviating, but I do hope you've found this useful as a checklist for your own writing, or maybe just knowing how to spot a difficult-to-follow tutorial will inspire you to keep going and find better resources when you get frustrated.&lt;/p&gt;

&lt;p&gt;And of course I am not perfect. Be sure to open issues on my own blog when you've found one that's really bad!&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>When I was a junior dev I'd look at some problems and think "This is hard because I'm not very good at this and need to get better" and now I look at a lot of those same problems and think, "This is hard because this is badly-designed garbage."</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Tue, 14 Jan 2025 21:46:45 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/when-i-was-a-junior-dev-id-look-at-some-problems-and-think-this-is-hard-because-im-not-very-good-3d72</link>
      <guid>https://dev.to/webbureaucrat/when-i-was-a-junior-dev-id-look-at-some-problems-and-think-this-is-hard-because-im-not-very-good-3d72</guid>
      <description></description>
      <category>career</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Emacs for Python and Poetry Using `basedpyright-langserver`</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Sun, 06 Oct 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/emacs-for-python-and-poetry-using-basedpyright-langserver-ca9</link>
      <guid>https://dev.to/webbureaucrat/emacs-for-python-and-poetry-using-basedpyright-langserver-ca9</guid>
      <description>&lt;p&gt;I am very pleased with my current emacs setup for Python, but I found setup to be a little tricky. I will document my setup here for my future self and for any other Pythonistas looking for a solid emacs config.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why basedpyright?
&lt;/h3&gt;

&lt;p&gt;Up to this point, I've been using &lt;code&gt;mypy --strict&lt;/code&gt; on the command line for all my typechecking needs, but mypy is quite slow even for very small codebases, and even in &lt;code&gt;--strict&lt;/code&gt; mode it is just not as strict as it could be. It's also not a language server, which I want for my emacs setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.basedpyright.com/latest/" rel="noopener noreferrer"&gt;basedpyright&lt;/a&gt; is a fork of pyright with some excellent improvements in both checking and in reliability. It is a fast and wonderfully strict typechecker with some good linting capabilities additionally.&lt;/p&gt;

&lt;p&gt;The only drawbacks I am experiencing are that it doesn't play quite as nicely as mypy with the &lt;code&gt;boto3-stubs&lt;/code&gt; clients for AWS and that it uses nonstandard &lt;code&gt;# pyright: ignore&lt;/code&gt; comments instead of the standard &lt;code&gt;# type: ignore&lt;/code&gt; comments, but I can live with those issues in favor of a rigorously strict type-checking experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring your Poetry projects to work with basedpyright or pyright
&lt;/h3&gt;

&lt;p&gt;If you have existing projects that use Poetry, you're going to want to fiddle a little with your virtual environment.&lt;/p&gt;

&lt;p&gt;Go to the root of each of your projects and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry config &lt;span class="nt"&gt;--local&lt;/span&gt; virtualenvs.in-project &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a &lt;em&gt;poetry.toml&lt;/em&gt; file if one does not already exist and add a corresponding setting.&lt;/p&gt;

&lt;p&gt;This, however, will &lt;em&gt;not&lt;/em&gt; actually move your existing virtual environment. In order for this change to take effect, you have to remove your existing virtual environment, which you can find by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry &lt;span class="nb"&gt;env &lt;/span&gt;info &lt;span class="nt"&gt;--path&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to add the &lt;em&gt;.venv&lt;/em&gt; path to your &lt;em&gt;.gitignore&lt;/em&gt; and the configuration for any other tools you might use, like pycodestyle, or you'll end up with quite a mess.&lt;/p&gt;

&lt;p&gt;Next, you should add a configuration section to your &lt;em&gt;pyproject.toml&lt;/em&gt; to tell basedpyright where to look for your virtual environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tool.pyright]&lt;/span&gt;
&lt;span class="py"&gt;venv&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;".venv"&lt;/span&gt;
&lt;span class="py"&gt;venvPath&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also do this in &lt;em&gt;pyrightconfig.json&lt;/em&gt; file if, unlike me, you do not already feel completely overrun with config files for different Python development tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing basedpyright as a language server
&lt;/h3&gt;

&lt;p&gt;One very nice thing about basedpyright over pyright is that it builds the nodejs dependency as a wheel, so you can be assured that basedpyright should work on your machine regardless of whether you have nodejs installed.&lt;/p&gt;

&lt;p&gt;For isolation, it is usually a good idea to install executable Python packages using pipx instead of pip. Let's go ahead and do that .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install &lt;/span&gt;basedpyright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a sanity check, consider running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;basedpyright &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installing basedpyright also gives you access to the&lt;code&gt;basedpyright-langserver&lt;/code&gt; command, but that's not really written for users to interact with, so if you run&lt;code&gt;basedpyright-langserver&lt;/code&gt; or&lt;code&gt;basedpyright-langserver --version&lt;/code&gt; or something, you'll get a nodejs stack trace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring emacs to use &lt;code&gt;basedpyright-langserver&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;I'll assume you as the reader know how to install packages from MELPA and have a preferred way to do it. Here are all the packages you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;company&lt;/li&gt;
&lt;li&gt;lsp-mode&lt;/li&gt;
&lt;li&gt;lsp-pyright&lt;/li&gt;
&lt;li&gt;lsp-ui&lt;/li&gt;
&lt;li&gt;python-mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get those installed and then open your &lt;em&gt;~/.emacs&lt;/em&gt; or your &lt;em&gt;~/.emacs.d/init.el&lt;/em&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="c1"&gt;;; lsp global settings&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;'after-init-hook&lt;/span&gt; &lt;span class="ss"&gt;'global-company-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;lsp-auto-guess-root&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;;; python&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'lsp-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;lsp-pyright-langserver-command&lt;/span&gt; &lt;span class="s"&gt;"basedpyright"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;'python-mode-hook&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'lsp-pyright&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should be all you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  A general tip for debugging lsp-mode
&lt;/h3&gt;

&lt;p&gt;If you feel like you've set everything up correctly and you're still having trouble getting lsp-mode to find packages that should be available in Poetry, one thing you might try is to go in and delete your &lt;em&gt;~/.emacs.d/.lsp-session-v1&lt;/em&gt;. This will have the effect of causing lsp-mode to forget about the project root and force it to look for it again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Happy coding!
&lt;/h3&gt;

&lt;p&gt;I hope this has given you a good head start on your Python development environment. If you have any questions, well, I'm a beginner with all this, and I probably can't help you, but I will consider merge requests if you have any extra tips or tricks for using basedpyright with emacs.&lt;/p&gt;

</description>
      <category>basedpyright</category>
      <category>emacs</category>
      <category>python</category>
    </item>
    <item>
      <title>A Font Family Choice for Pragmatism and Disability Allyship</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Mon, 30 Sep 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/a-font-family-choice-for-pragmatism-and-disability-allyship-4j9k</link>
      <guid>https://dev.to/webbureaucrat/a-font-family-choice-for-pragmatism-and-disability-allyship-4j9k</guid>
      <description>&lt;p&gt;&lt;em&gt;A side note for Dev.to readers: if you want to see this font in action, read this article instead in &lt;a href="https://webbureaucrat.gitlab.io/articles/a-font-family-choice-for-pragmatism-and-disability-allyship/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's no need for this to be a full length article, but I've had a couple occasions recently to evangelize my favorite non-monospace font, and it occurs to me this might be a good time to collect and share my thoughts about the font choice I've made for my blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atkinson Hyperlegible is font choice for disability allyship
&lt;/h3&gt;

&lt;p&gt;All of the text in my blog (except for the code blocks) is &lt;a href="https://www.brailleinstitute.org/freefont/" rel="noopener noreferrer"&gt;Atkinson Hyperlegible&lt;/a&gt;. The linked page has an excellent and brief rundown of what makes this font special. Rather than reiterate all those points here, I would encourage you to take just about sixty seconds to scroll the linked page and return to this article if you'd like.&lt;/p&gt;

&lt;p&gt;The long and the short of it is that Atkinson Hyperlegible is a very thoughtfully designed font from the standpoint of readability and low-vision accessibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atkinson Hyperlegible is a font choice for any pragmatist
&lt;/h3&gt;

&lt;p&gt;Look, occasionally in technology you come across a good decision with &lt;em&gt;no&lt;/em&gt; tradeoffs, only benefits, and nowhere is that more clear than in the world of disability access on the web. Sometimes sighted people connect from a crumby internet connection and the images don't load, and in those moments, sighted people really appreciate your alt text on images, for example. Proper headings and other best practices for semantic markup help enable navigation for screen reader users, but they also improve your search ranking!&lt;/p&gt;

&lt;p&gt;This is another example of that. Every user who is at all sighted benefits from a more legible font choice, myself very much included.&lt;/p&gt;

&lt;p&gt;I am &lt;em&gt;not&lt;/em&gt; a designer, as anyone looking at my website will tell you. I'm technically competent on the frontend, but I am a backend woman, and that's where I belong.&lt;/p&gt;

&lt;p&gt;But I'm also a user, and, in that sense, my preferences are as valid as anyone else's, and as a sighted user I have to say I am &lt;strong&gt;extremely bleeding tired&lt;/strong&gt; of not being able to tell the difference between l, 1, and I. This year especially, I'm sure I'm not the only person who is tired of accidentally parsing "AI" as "Al" and vice versa. May as well add some A1 sauce because I am cooked switching back and forth between news stories about generative AI and the Al Smith Dinner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atkinson Hyperlegible may be a font choice for you
&lt;/h3&gt;

&lt;p&gt;I hope to see Atkinson Hyperlegible used more widely, both because I want my low-vision neighbors to be able to enjoy the same content I can and because I benefit from Atkinson Hyperlegible, too.&lt;/p&gt;

&lt;p&gt;So I hope you'll consider using Atkinson Hyperlegible or even consider opening issues on your favorite projects recommending Atkinson Hyperlegible as an option. If not--if it's just not your cup of tea--I hope you've at least enjoyed learning a bit of trivia about a unique font that makes interesting choices.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>design</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Iced for Desktop Development in Rust</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Mon, 25 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/iced-for-desktop-development-in-rust-2e0h</link>
      <guid>https://dev.to/webbureaucrat/iced-for-desktop-development-in-rust-2e0h</guid>
      <description>&lt;p&gt;As someone who loves Elm and has recently fallen in love with Rust, I was delighted to learn there are not just one but &lt;em&gt;two&lt;/em&gt; Rust frameworks modeled on the Elm Architecture. If you're not familiar, the Elm Architecture is a pain-free way of developing fast, responsive, asynchronous-by-default front-ends. Let's see it in action by developing a simple "Hello, world" app.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I'm using &lt;code&gt;iced&lt;/code&gt; version &lt;code&gt;0.10.0&lt;/code&gt;. Iced is currently under rapid development with frequent breaking changes. It's possible these directions won't work as expected in a future release.&lt;/em&gt; As always, if something breaks, &lt;a href="https://gitlab.com/webbureaucrat/webbureaucrat.gitlab.io/-/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; or submit a pull request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Let's start with a fresh application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo init hello-iced
&lt;span class="nb"&gt;cd &lt;/span&gt;hello-iced
cargo add iced
cargo build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the build succeeds, we're off to a good start.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing a State Model for Iced in Rust
&lt;/h3&gt;

&lt;p&gt;The easiest part of the Elm Architecture to understand is the model state, so let's start there. The model state represents the whole state of the application--everything you would need to know in order to draw any given application screen. As you can imagine, state models are often quite large, but our application will need only one piece of information: whom to greet (by default: the world). That's easy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="n"&gt;addressee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Writing a Message Enum for Iced in Rust
&lt;/h3&gt;

&lt;p&gt;Next, we need our Message. A message is an enum that represents all the ways that our model can &lt;em&gt;update&lt;/em&gt; according to the logic of our application. For example, you might have a counter that can increment or a counter that can either increment and decrement, or a counter that can increment, decrement, or reset, all depending on the logic of your application.&lt;/p&gt;

&lt;p&gt;In our case, we only have one field in our model &lt;code&gt;struct&lt;/code&gt;, and it can only be updated through a text input, so let's write an enum to that effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;TextBoxChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&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;We can see that our enum takes a &lt;code&gt;String&lt;/code&gt;. This represents the new string to which we will update our model. Also note that it derives &lt;code&gt;Clone&lt;/code&gt; and &lt;code&gt;Debug&lt;/code&gt;. This is required by the framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing &lt;code&gt;iced::Application&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now the real work begins: turning our model into an Iced &lt;code&gt;Application&lt;/code&gt;. Let's begin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="n"&gt;addressee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;TextBoxChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need four types for our application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Executor&lt;/code&gt; - The only type provided by the framework is &lt;code&gt;Default&lt;/code&gt;, which will suffice for our purposes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Flags&lt;/code&gt; - represents any data we want to initialize our application. We have no flags to pass, so the unit type will suffice.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Message&lt;/code&gt; - this is the &lt;code&gt;HelloMessage&lt;/code&gt; we defined earlier.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Theme&lt;/code&gt; - the theme of the application.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;addressee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;TextBoxChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Theme&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;Next we need a function that initializes our model. Our model will default to greeting, well, the world.&lt;/p&gt;

&lt;p&gt;Start by adding &lt;code&gt;use iced::Command;&lt;/code&gt; at the top. A command is an asynchronous action that the framework will take on next. We don't need to start any commands on startup, so we'll initialize with &lt;code&gt;Command::none()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;addressee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nn"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;none&lt;/span&gt;&lt;span class="p"&gt;()&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;We also need a function which takes the &lt;code&gt;&amp;amp;self&lt;/code&gt; state model and returns a title for the title bar at the top of the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;addressee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nn"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Greet the World"&lt;/span&gt;&lt;span class="p"&gt;)&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;Now we're getting to the real meat of the application: the &lt;code&gt;update&lt;/code&gt; and &lt;code&gt;view&lt;/code&gt;functions.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;update&lt;/code&gt; function takes our state model and mutates it based on the given message. It also gives us the opportunity to start another &lt;code&gt;Command&lt;/code&gt; after mutating our state. For example, a common use case for a submit action message is to change part of the state to represent that the state is "Loading..." and then to start a command to fetch some data based on the submission. We only have one kind of message, so our update function will be very simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;TextBoxChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.addressee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nn"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&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;Finally, we can write our view. Let's start by &lt;code&gt;use&lt;/code&gt;ing some relevant parts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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;We build out our view programmatically using the&lt;code&gt;push&lt;/code&gt; method, and then convert the final result to an &lt;code&gt;Element&lt;/code&gt; using&lt;code&gt;into()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, {0}."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.addressee&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="nf"&gt;.width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Fill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.horizontal_alignment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Horizontal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;row1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TextInput&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Renderer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.addressee&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.on_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TextBoxChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;row2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into&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;h3&gt;
  
  
  Writing a &lt;code&gt;main&lt;/code&gt; function to &lt;code&gt;run&lt;/code&gt; an Iced &lt;code&gt;Application&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, we need to &lt;code&gt;run&lt;/code&gt; our application from the &lt;code&gt;main&lt;/code&gt; function. Make sure to &lt;code&gt;use&lt;/code&gt; &lt;code&gt;iced::Application&lt;/code&gt; to bring the &lt;code&gt;run&lt;/code&gt; function into scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nn"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&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;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;In conclusion, I hope this has been a helpful introduction to the Iced framework and the Elm Architecture. The architecture has a learning curve, so I figure the more learning resources out there, the better.&lt;/p&gt;

&lt;p&gt;For reference, this is the full source code:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/main.rs&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;addressee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;TextBoxChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;addressee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nn"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Greet the World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;TextBoxChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.addressee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nn"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, {0}."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.addressee&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="nf"&gt;.width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Fill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.horizontal_alignment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Horizontal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;row1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TextInput&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Renderer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.addressee&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.on_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;HelloMessage&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TextBoxChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;row2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()&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;



</description>
      <category>iced</category>
      <category>rust</category>
    </item>
    <item>
      <title>Setting and Reading Session Cookies in Rust with Actix Web</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Mon, 17 Jul 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/setting-and-reading-session-cookies-in-rust-with-actix-web-5fdf</link>
      <guid>https://dev.to/webbureaucrat/setting-and-reading-session-cookies-in-rust-with-actix-web-5fdf</guid>
      <description>&lt;p&gt;In case it's not readily apparent, I've been having some trouble picking a backend stack recently, but, at the risk of jinxing it, I really think Rust is the backend for me, and Actix Web is a blindingly fast MVC framework for Rust with an elegant and functional middleware system. As with all web apps, my first challenge is persisting and managing state between requests, so let's get into user session management in Actix Web.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting with Hello World in Rust with Actix Web
&lt;/h3&gt;

&lt;p&gt;For completeness, I'm going to start with &lt;code&gt;cargo new&lt;/code&gt;. Feel free to skip ahead.&lt;/p&gt;

&lt;p&gt;You can start with &lt;code&gt;cargo new actix-kata&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you enter your directory, you should find a "Hello, world" program. If you&lt;code&gt;cargo run&lt;/code&gt; it, you should get "Hello, world" printed to the screen.&lt;/p&gt;

&lt;p&gt;To add Actix Web to your project, run &lt;code&gt;cargo add actix-web&lt;/code&gt;. If you &lt;code&gt;cargo build&lt;/code&gt; or &lt;code&gt;cargo run&lt;/code&gt; again, it should install Actix Web and all its dependencies.&lt;/p&gt;

&lt;p&gt;Then replace &lt;em&gt;src/main.rs&lt;/em&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::get(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting started with &lt;code&gt;actix-session&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;actix-session&lt;/code&gt; is it's own Rust crate, separate from &lt;code&gt;actix-web&lt;/code&gt;. It has a feature flag for cookie sessions. To use it, install it with &lt;code&gt;cargo add actix-session --features cookie-session&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our goal will be to build out a &lt;code&gt;SessionMiddleware&amp;lt;CookieSessionStore&amp;gt;&lt;/code&gt;. We can do that with a&lt;a href="https://docs.rs/actix-session/latest/actix_session/config/struct.SessionMiddlewareBuilder.html" rel="noopener noreferrer"&gt;&lt;code&gt;SessionMiddlewareBuilder&lt;/code&gt;&lt;/a&gt;. To put a fine point on it, let's break it out into its own function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;SessionMiddleware&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;CookieSessionStore&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::get(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;session_middleware&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CookieSessionStore&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nn"&gt;CookieSessionStore&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;session_middleware&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;//register session middleware&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This accepts all defaults and registers the session middleware in the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building out a cookie session in Actix Web
&lt;/h3&gt;

&lt;p&gt;Now let's fill in some details using the provided builder methods. (Some of these are set by default, but in the interest of a good demonstration, let's make as much explicit as we can.)&lt;/p&gt;

&lt;p&gt;Importantly, many possible configuration items are matters of security both for the application and for the user, so it is a very good idea to familiarize oneself with each item in the documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;config&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;BrowserSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CookieContentSecurity&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;CookieSessionStore&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SameSite&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::get(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;session_middleware&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CookieSessionStore&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nn"&gt;CookieSessionStore&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my-kata-cookie"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// arbitrary name&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_secure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// https only&lt;/span&gt;
    &lt;span class="nf"&gt;.session_lifecycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;BrowserSession&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// expire at end of session&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_same_site&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;SameSite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Strict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="nf"&gt;.cookie_content_security&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CookieContentSecurity&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Private&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// encrypt&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_http_only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// disallow scripts from reading&lt;/span&gt;
    &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;session_middleware&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reading from a cookie in Actix Web
&lt;/h3&gt;

&lt;p&gt;Reading from and writing to cookies is very simple with the &lt;code&gt;Session&lt;/code&gt;extractor. Just include a parameter typed as &lt;code&gt;Session&lt;/code&gt;, and the framework will take care of the rest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;config&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;BrowserSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CookieContentSecurity&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;CookieSessionStore&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SameSite&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;Json&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::get(&lt;/span&gt;&lt;span class="s"&gt;"get_session"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="py"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message_option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;message_option&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Not set."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;InternalServerError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Session error."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::get(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;session_middleware&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CookieSessionStore&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nn"&gt;CookieSessionStore&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my-kata-cookie"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_secure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.session_lifecycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;BrowserSession&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_same_site&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;SameSite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Strict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_content_security&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CookieContentSecurity&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Private&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_http_only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;session_middleware&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting the session cookie in Actix Web
&lt;/h3&gt;

&lt;p&gt;We can use &lt;code&gt;serde&lt;/code&gt; to create an endpoint to set the session. We'll also need the &lt;code&gt;derive&lt;/code&gt; feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add serde &lt;span class="nt"&gt;--features&lt;/span&gt; derive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, your &lt;em&gt;Cargo.toml&lt;/em&gt; should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[package]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"actix-kata"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;edition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2021"&lt;/span&gt;

&lt;span class="c"&gt;# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html&lt;/span&gt;

&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;actix-session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.7.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"cookie-session"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;actix-web&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"4.3.1"&lt;/span&gt;
&lt;span class="py"&gt;serde&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.0.164"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"derive"&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;With &lt;code&gt;serde&lt;/code&gt;, we can make a deserializable &lt;code&gt;struct&lt;/code&gt; to model our input and then extract it simply by putting it in the signature of our method. The framework will handle the rest.&lt;/p&gt;

&lt;p&gt;Then we can insert the message using &lt;code&gt;session.insert&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;main.rs&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;config&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;BrowserSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CookieContentSecurity&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_session&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;CookieSessionStore&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SameSite&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;Json&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(serde::Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;CookieModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::get(&lt;/span&gt;&lt;span class="s"&gt;"get_session"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="py"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message_option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;message_option&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Not set."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;InternalServerError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::get(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CookieModel&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Responder&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="nf"&gt;.insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="py"&gt;.message&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Created."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;InternalServerError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;session_middleware&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CookieSessionStore&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;SessionMiddleware&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nn"&gt;CookieSessionStore&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my-kata-cookie"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_secure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.session_lifecycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;BrowserSession&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_same_site&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;SameSite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Strict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_content_security&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CookieContentSecurity&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Private&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.cookie_http_only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;session_middleware&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"set_session"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_session&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;And that's really it. Make sure you set your mime type for the &lt;code&gt;/set_session&lt;/code&gt; request to &lt;code&gt;application/json&lt;/code&gt; if you're testing. This has been helpful to me as I get into Actix Web middleware for the first time, so I hope it has been helpful to you.&lt;/p&gt;

</description>
      <category>actix</category>
      <category>rust</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Writing a (Nix-Friendly) Hello World Web App in Haskell with Scotty</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Mon, 10 Jul 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/writing-a-nix-friendly-hello-world-web-app-in-haskell-with-scotty-388p</link>
      <guid>https://dev.to/webbureaucrat/writing-a-nix-friendly-hello-world-web-app-in-haskell-with-scotty-388p</guid>
      <description>&lt;p&gt;Okay, so this article has been written before, and I don't have a lot new to add, but some of these tutorials are getting pretty old, and the ones that aren't use &lt;code&gt;stack&lt;/code&gt;, which I personally am avoiding as it doesn't play well with NixOS, so at least for me, for future reference, this tutorial will be useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites for Haskell and Scotty
&lt;/h3&gt;

&lt;p&gt;The first thing we need is a working development environment. I recommend Nix for this because I've fallen in love with the reproducibility of Nix scripts. Using Nix, we can download and run packages on the fly without messing with the rest of our system. Whether we're using nix or not, we need&lt;code&gt;cabal-install&lt;/code&gt;, &lt;code&gt;ghc&lt;/code&gt;, &lt;code&gt;git&lt;/code&gt;, and &lt;code&gt;zlib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;(A couple of those are not strictly intuitive, which is one reason why I'm writing this tutorial. &lt;code&gt;git&lt;/code&gt; is required for &lt;code&gt;cabal-install&lt;/code&gt; to work properly, and &lt;code&gt;zlib&lt;/code&gt; is a dependency of Scotty.)&lt;/p&gt;

&lt;p&gt;In Nix, we can simply start a new environment with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nix-shell &lt;span class="nt"&gt;--packages&lt;/span&gt; bash cabal-install ghc git zlib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initializing a Hello World App in Haskell with &lt;code&gt;cabal&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;We can initialize a new web app in Haskell with &lt;code&gt;cabal init&lt;/code&gt;. I won't go through all the steps because the defaults are generally very sensible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;webcd webcabal init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For completeness, here's my sample &lt;em&gt;.cabal&lt;/em&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="err"&gt;cabal-version:&lt;/span&gt;      &lt;span class="err"&gt;3.0&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;The&lt;/span&gt; &lt;span class="err"&gt;cabal-version&lt;/span&gt; &lt;span class="err"&gt;field&lt;/span&gt; &lt;span class="err"&gt;refers&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;version&lt;/span&gt; &lt;span class="err"&gt;of&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;.cabal&lt;/span&gt; &lt;span class="err"&gt;specification,&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;and&lt;/span&gt; &lt;span class="err"&gt;can&lt;/span&gt; &lt;span class="err"&gt;be&lt;/span&gt; &lt;span class="err"&gt;different&lt;/span&gt; &lt;span class="err"&gt;from&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;cabal-install&lt;/span&gt; &lt;span class="err"&gt;(the&lt;/span&gt; &lt;span class="err"&gt;tool)&lt;/span&gt; &lt;span class="err"&gt;version&lt;/span&gt; &lt;span class="err"&gt;and&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Cabal&lt;/span&gt; &lt;span class="err"&gt;(the&lt;/span&gt; &lt;span class="err"&gt;library)&lt;/span&gt; &lt;span class="err"&gt;version&lt;/span&gt; &lt;span class="err"&gt;you&lt;/span&gt; &lt;span class="err"&gt;are&lt;/span&gt; &lt;span class="err"&gt;using.&lt;/span&gt; &lt;span class="err"&gt;As&lt;/span&gt; &lt;span class="err"&gt;such,&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;Cabal&lt;/span&gt; &lt;span class="err"&gt;(the&lt;/span&gt; &lt;span class="err"&gt;library)&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;version&lt;/span&gt; &lt;span class="err"&gt;used&lt;/span&gt; &lt;span class="err"&gt;must&lt;/span&gt; &lt;span class="err"&gt;be&lt;/span&gt; &lt;span class="err"&gt;equal&lt;/span&gt; &lt;span class="err"&gt;or&lt;/span&gt; &lt;span class="err"&gt;greater&lt;/span&gt; &lt;span class="err"&gt;than&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;version&lt;/span&gt; &lt;span class="err"&gt;stated&lt;/span&gt; &lt;span class="err"&gt;in&lt;/span&gt; &lt;span class="err"&gt;this&lt;/span&gt; &lt;span class="err"&gt;field.&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Starting&lt;/span&gt; &lt;span class="err"&gt;from&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;specification&lt;/span&gt; &lt;span class="err"&gt;version&lt;/span&gt; &lt;span class="err"&gt;2.2,&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;cabal-version&lt;/span&gt; &lt;span class="err"&gt;field&lt;/span&gt; &lt;span class="err"&gt;must&lt;/span&gt; &lt;span class="err"&gt;be&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;first&lt;/span&gt; &lt;span class="err"&gt;thing&lt;/span&gt; &lt;span class="err"&gt;in&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;cabal&lt;/span&gt; &lt;span class="err"&gt;file.&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Initial&lt;/span&gt; &lt;span class="err"&gt;package&lt;/span&gt; &lt;span class="err"&gt;description&lt;/span&gt; &lt;span class="err"&gt;'web'&lt;/span&gt; &lt;span class="err"&gt;generated&lt;/span&gt; &lt;span class="err"&gt;by&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;'cabal&lt;/span&gt; &lt;span class="err"&gt;init'.&lt;/span&gt; &lt;span class="err"&gt;For&lt;/span&gt; &lt;span class="err"&gt;further&lt;/span&gt; &lt;span class="err"&gt;documentation,&lt;/span&gt; &lt;span class="err"&gt;see:&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt;   &lt;span class="err"&gt;http://haskell.org/cabal/users-guide/&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;The&lt;/span&gt; &lt;span class="err"&gt;name&lt;/span&gt; &lt;span class="err"&gt;of&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;package.&lt;/span&gt;
&lt;span class="err"&gt;name:&lt;/span&gt;               &lt;span class="err"&gt;web&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;The&lt;/span&gt; &lt;span class="err"&gt;package&lt;/span&gt; &lt;span class="err"&gt;version.&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;See&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;Haskell&lt;/span&gt; &lt;span class="err"&gt;package&lt;/span&gt; &lt;span class="err"&gt;versioning&lt;/span&gt; &lt;span class="err"&gt;policy&lt;/span&gt; &lt;span class="err"&gt;(PVP)&lt;/span&gt; &lt;span class="err"&gt;for&lt;/span&gt; &lt;span class="err"&gt;standards&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;guiding&lt;/span&gt; &lt;span class="err"&gt;when&lt;/span&gt; &lt;span class="err"&gt;and&lt;/span&gt; &lt;span class="err"&gt;how&lt;/span&gt; &lt;span class="err"&gt;versions&lt;/span&gt; &lt;span class="err"&gt;should&lt;/span&gt; &lt;span class="err"&gt;be&lt;/span&gt; &lt;span class="err"&gt;incremented.&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;https://pvp.haskell.org&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;PVP&lt;/span&gt; &lt;span class="err"&gt;summary:&lt;/span&gt;     &lt;span class="err"&gt;+-+-------&lt;/span&gt; &lt;span class="err"&gt;breaking&lt;/span&gt; &lt;span class="err"&gt;API&lt;/span&gt; &lt;span class="err"&gt;changes&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt;                  &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;+-----&lt;/span&gt; &lt;span class="err"&gt;non-breaking&lt;/span&gt; &lt;span class="err"&gt;API&lt;/span&gt; &lt;span class="err"&gt;additions&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt;                  &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;+---&lt;/span&gt; &lt;span class="err"&gt;code&lt;/span&gt; &lt;span class="err"&gt;changes&lt;/span&gt; &lt;span class="err"&gt;with&lt;/span&gt; &lt;span class="err"&gt;no&lt;/span&gt; &lt;span class="err"&gt;API&lt;/span&gt; &lt;span class="err"&gt;change&lt;/span&gt;
&lt;span class="err"&gt;version:&lt;/span&gt;            &lt;span class="err"&gt;0.1.0.0&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;A&lt;/span&gt; &lt;span class="err"&gt;short&lt;/span&gt; &lt;span class="err"&gt;(one-line)&lt;/span&gt; &lt;span class="err"&gt;description&lt;/span&gt; &lt;span class="err"&gt;of&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;package.&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;synopsis:&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;A&lt;/span&gt; &lt;span class="err"&gt;longer&lt;/span&gt; &lt;span class="err"&gt;description&lt;/span&gt; &lt;span class="err"&gt;of&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;package.&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;description:&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;The&lt;/span&gt; &lt;span class="err"&gt;license&lt;/span&gt; &lt;span class="err"&gt;under&lt;/span&gt; &lt;span class="err"&gt;which&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;package&lt;/span&gt; &lt;span class="err"&gt;is&lt;/span&gt; &lt;span class="err"&gt;released.&lt;/span&gt;
&lt;span class="err"&gt;license:&lt;/span&gt;            &lt;span class="err"&gt;GPL-3.0-or-later&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;The&lt;/span&gt; &lt;span class="err"&gt;file&lt;/span&gt; &lt;span class="err"&gt;containing&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;license&lt;/span&gt; &lt;span class="err"&gt;text.&lt;/span&gt;
&lt;span class="err"&gt;license-file:&lt;/span&gt;       &lt;span class="err"&gt;LICENSE&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;The&lt;/span&gt; &lt;span class="err"&gt;package&lt;/span&gt; &lt;span class="err"&gt;author(s).&lt;/span&gt;
&lt;span class="err"&gt;author:&lt;/span&gt;             &lt;span class="err"&gt;eleanorofs&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;An&lt;/span&gt; &lt;span class="err"&gt;email&lt;/span&gt; &lt;span class="err"&gt;address&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;which&lt;/span&gt; &lt;span class="err"&gt;users&lt;/span&gt; &lt;span class="err"&gt;can&lt;/span&gt; &lt;span class="err"&gt;send&lt;/span&gt; &lt;span class="err"&gt;suggestions,&lt;/span&gt; &lt;span class="err"&gt;bug&lt;/span&gt; &lt;span class="err"&gt;reports,&lt;/span&gt; &lt;span class="err"&gt;and&lt;/span&gt; &lt;span class="err"&gt;patches.&lt;/span&gt;
&lt;span class="err"&gt;maintainer:&lt;/span&gt;         &lt;span class="err"&gt;lu80mmgmt5nm@blurmail.net&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;A&lt;/span&gt; &lt;span class="err"&gt;copyright&lt;/span&gt; &lt;span class="err"&gt;notice.&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;copyright:&lt;/span&gt;
&lt;span class="err"&gt;category:&lt;/span&gt;           &lt;span class="err"&gt;Web&lt;/span&gt;
&lt;span class="err"&gt;build-type:&lt;/span&gt;         &lt;span class="err"&gt;Simple&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Extra&lt;/span&gt; &lt;span class="err"&gt;doc&lt;/span&gt; &lt;span class="err"&gt;files&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;be&lt;/span&gt; &lt;span class="err"&gt;distributed&lt;/span&gt; &lt;span class="err"&gt;with&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;package,&lt;/span&gt; &lt;span class="err"&gt;such&lt;/span&gt; &lt;span class="err"&gt;as&lt;/span&gt; &lt;span class="err"&gt;a&lt;/span&gt; &lt;span class="err"&gt;CHANGELOG&lt;/span&gt; &lt;span class="err"&gt;or&lt;/span&gt; &lt;span class="err"&gt;a&lt;/span&gt; &lt;span class="err"&gt;README.&lt;/span&gt;
&lt;span class="err"&gt;extra-doc-files:&lt;/span&gt;    &lt;span class="err"&gt;CHANGELOG.md&lt;/span&gt;

&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Extra&lt;/span&gt; &lt;span class="err"&gt;source&lt;/span&gt; &lt;span class="err"&gt;files&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;be&lt;/span&gt; &lt;span class="err"&gt;distributed&lt;/span&gt; &lt;span class="err"&gt;with&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;package,&lt;/span&gt; &lt;span class="err"&gt;such&lt;/span&gt; &lt;span class="err"&gt;as&lt;/span&gt; &lt;span class="err"&gt;examples,&lt;/span&gt; &lt;span class="err"&gt;or&lt;/span&gt; &lt;span class="err"&gt;a&lt;/span&gt; &lt;span class="err"&gt;tutorial&lt;/span&gt; &lt;span class="err"&gt;module.&lt;/span&gt;
&lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;extra-source-files:&lt;/span&gt;

&lt;span class="err"&gt;common&lt;/span&gt; &lt;span class="err"&gt;warnings&lt;/span&gt;
    &lt;span class="err"&gt;ghc-options:&lt;/span&gt; &lt;span class="err"&gt;-Wall&lt;/span&gt;

&lt;span class="err"&gt;executable&lt;/span&gt; &lt;span class="err"&gt;web&lt;/span&gt;
    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Import&lt;/span&gt; &lt;span class="err"&gt;common&lt;/span&gt; &lt;span class="err"&gt;warning&lt;/span&gt; &lt;span class="err"&gt;flags.&lt;/span&gt;
    &lt;span class="err"&gt;import:&lt;/span&gt;           &lt;span class="err"&gt;warnings&lt;/span&gt;

    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;.hs&lt;/span&gt; &lt;span class="err"&gt;or&lt;/span&gt; &lt;span class="err"&gt;.lhs&lt;/span&gt; &lt;span class="err"&gt;file&lt;/span&gt; &lt;span class="err"&gt;containing&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;Main&lt;/span&gt; &lt;span class="err"&gt;module.&lt;/span&gt;
    &lt;span class="err"&gt;main-is:&lt;/span&gt;          &lt;span class="err"&gt;Main.hs&lt;/span&gt;

    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Modules&lt;/span&gt; &lt;span class="err"&gt;included&lt;/span&gt; &lt;span class="err"&gt;in&lt;/span&gt; &lt;span class="err"&gt;this&lt;/span&gt; &lt;span class="err"&gt;executable,&lt;/span&gt; &lt;span class="err"&gt;other&lt;/span&gt; &lt;span class="err"&gt;than&lt;/span&gt; &lt;span class="err"&gt;Main.&lt;/span&gt;
    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;other-modules:&lt;/span&gt;

    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;LANGUAGE&lt;/span&gt; &lt;span class="err"&gt;extensions&lt;/span&gt; &lt;span class="err"&gt;used&lt;/span&gt; &lt;span class="err"&gt;by&lt;/span&gt; &lt;span class="err"&gt;modules&lt;/span&gt; &lt;span class="err"&gt;in&lt;/span&gt; &lt;span class="err"&gt;this&lt;/span&gt; &lt;span class="err"&gt;package.&lt;/span&gt;
    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;other-extensions:&lt;/span&gt;

    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Other&lt;/span&gt; &lt;span class="err"&gt;library&lt;/span&gt; &lt;span class="err"&gt;packages&lt;/span&gt; &lt;span class="err"&gt;from&lt;/span&gt; &lt;span class="err"&gt;which&lt;/span&gt; &lt;span class="err"&gt;modules&lt;/span&gt; &lt;span class="err"&gt;are&lt;/span&gt; &lt;span class="err"&gt;imported.&lt;/span&gt;
    &lt;span class="err"&gt;build-depends:&lt;/span&gt;    &lt;span class="err"&gt;base&lt;/span&gt; &lt;span class="py"&gt;^&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;4.15&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;

    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Directories&lt;/span&gt; &lt;span class="err"&gt;containing&lt;/span&gt; &lt;span class="err"&gt;source&lt;/span&gt; &lt;span class="err"&gt;files.&lt;/span&gt;
    &lt;span class="err"&gt;hs-source-dirs:&lt;/span&gt;   &lt;span class="err"&gt;app&lt;/span&gt;

    &lt;span class="err"&gt;--&lt;/span&gt; &lt;span class="err"&gt;Base&lt;/span&gt; &lt;span class="err"&gt;language&lt;/span&gt; &lt;span class="err"&gt;which&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;package&lt;/span&gt; &lt;span class="err"&gt;is&lt;/span&gt; &lt;span class="err"&gt;written&lt;/span&gt; &lt;span class="err"&gt;in.&lt;/span&gt;
    &lt;span class="err"&gt;default-language:&lt;/span&gt; &lt;span class="err"&gt;Haskell2010&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To ensure your project is created properly, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cabal update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cabal run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see "Hello Haskell" printed in addition to some other output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Scotty to your Haskell project
&lt;/h3&gt;

&lt;p&gt;To make Scotty available for import, add it as a build dependency in your_.cabal_ file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Other library packages from which modules are imported.
build-depends: base ^&amp;gt;=4.15.1.0, scotty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can test that your &lt;em&gt;.cabal&lt;/em&gt; file is correct by going ahead and importing&lt;code&gt;Web.Scotty&lt;/code&gt; into your &lt;em&gt;app/Main.hs&lt;/em&gt; file and running again with the command above.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;app/Main.hs&lt;/em&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="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Main&lt;/span&gt; &lt;span class="kr"&gt;where&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;Web.Scotty&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;putStrLn&lt;/span&gt; &lt;span class="s"&gt;"Hello, Haskell!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your app compiles and runs successfully, you know you're ready to start writing code with Scotty.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing a "Hello, world" action in Scotty
&lt;/h3&gt;

&lt;p&gt;In order to use Scotty (with reasonable developer ergonomics), you'll want the &lt;code&gt;OverloadedStrings&lt;/code&gt; language extension. This allows string literals to be used as other string-like objects when appropriate.&lt;/p&gt;

&lt;p&gt;Once you have &lt;code&gt;OverloadedStrings&lt;/code&gt;, you can write a Scotty &lt;code&gt;ActionM&lt;/code&gt; action for greeting the world.&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="cp"&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;
&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Main&lt;/span&gt; &lt;span class="kr"&gt;where&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;Web.Scotty&lt;/span&gt;

&lt;span class="n"&gt;homeAction&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Scotty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;ActionM&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;homeAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Scotty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;h1&amp;gt;Hello, world&amp;lt;/h1&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ActionM&lt;/code&gt;s are monads, which means technically we can write our action as a&lt;code&gt;do&lt;/code&gt; block like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;app/Main.hs&lt;/em&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="cp"&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;
&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Main&lt;/span&gt; &lt;span class="kr"&gt;where&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;Web.Scotty&lt;/span&gt;

&lt;span class="n"&gt;homeAction&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Scotty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;ActionM&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;homeAction&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;Web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Scotty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;h1&amp;gt;Hello, world&amp;lt;/h1&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...although this may look ugly for trivial examples like the one shown here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specifying a port and running a server in Scotty
&lt;/h3&gt;

&lt;p&gt;Finally, we're ready to create our server. This example uses port 3000.&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="cp"&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;

&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Main&lt;/span&gt; &lt;span class="kr"&gt;where&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;Web.Scotty&lt;/span&gt;
&lt;span class="n"&gt;homeAction&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Scotty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;ActionM&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;homeAction&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;Web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Scotty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;h1&amp;gt;Hello, world&amp;lt;/h1&amp;gt;"&lt;/span&gt;

&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;main&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;Web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Scotty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scotty&lt;/span&gt; &lt;span class="mi"&gt;3000&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;Web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Scotty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; 
        &lt;span class="kr"&gt;do&lt;/span&gt; &lt;span class="n"&gt;homeAction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run this with &lt;code&gt;cabal run&lt;/code&gt;, you should be able to see your server running at &lt;code&gt;http://localhost:3000/&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  In conclusion
&lt;/h3&gt;

&lt;p&gt;Whether you use Nix or not, I hope this has been helpful to people getting started with Scotty.&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>functional</category>
      <category>nixos</category>
      <category>scotty</category>
    </item>
    <item>
      <title>Running and Connecting to Postgres Using Docker Compose</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Thu, 15 Jun 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/running-and-connecting-to-postgres-using-docker-compose-2494</link>
      <guid>https://dev.to/webbureaucrat/running-and-connecting-to-postgres-using-docker-compose-2494</guid>
      <description>&lt;p&gt;Setting up a new development environment from scratch can feel like a slog. This is a quick copy-paste recipe for getting up and running quickly with Postgres in &lt;code&gt;docker compose&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start with a .env file
&lt;/h3&gt;

&lt;p&gt;At the very least, we know we will need a &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt; environment variable, and our .env file doesn't rely on any other files, so it's a good place to start.&lt;/p&gt;

&lt;p&gt;I personally am not crazy about hiding files by beginning them with periods, so I'm going to call my file &lt;em&gt;database.env&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;database.env&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres_user
&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres_password
&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres_database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It goes without saying, but this is for &lt;em&gt;local development&lt;/em&gt;. Sensitive information for any database you intend to stand up for a while should be treated better than this. Use stronger passwords, and don't publish them in a blog post on the Internet, etc., etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create database scripts
&lt;/h3&gt;

&lt;p&gt;This section is more or less the "Draw the rest of the owl" portion of this article. The idea here is to create whatever database scripts--tables, stored procedures, etc--in &lt;em&gt;./database/docker-entrypoint-initdb.d&lt;/em&gt;. Any &lt;em&gt;.sql&lt;/em&gt; or compressed &lt;em&gt;.sql&lt;/em&gt; file in this folder will be run by the database at startup. (Other file extensions are supported. See &lt;a href="https://hub.docker.com/_/postgres/" rel="noopener noreferrer"&gt;the official documentation&lt;/a&gt; for more.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a &lt;em&gt;docker-compose.yml&lt;/em&gt; file
&lt;/h3&gt;

&lt;p&gt;Now we're ready to get started with our docker compose file. There's no magic here--we're just exposing our ports, referencing our &lt;em&gt;database.env&lt;/em&gt; file, and feeding in our scripts from our scripts directory.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;docker-compose.yml&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;database.env"&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./database/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should now be able to run this with &lt;code&gt;docker compose up&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to a locally-running Postgres container
&lt;/h3&gt;

&lt;p&gt;With that compose file running, we can connect via SSH like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nb"&gt;exec &lt;/span&gt;database bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that "database" is the identifier chosen in the &lt;em&gt;docker-compose.yml&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, we can run psql from within the container to run commands directly inside the container. Use the values from your &lt;em&gt;database.env&lt;/em&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;--dbname&lt;/span&gt; postgres_database &lt;span class="nt"&gt;--host&lt;/span&gt; localhost &lt;span class="nt"&gt;--username&lt;/span&gt; postgres_user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be shortened to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;-d&lt;/span&gt; postgres_database &lt;span class="nt"&gt;-h&lt;/span&gt; localhost &lt;span class="nt"&gt;-U&lt;/span&gt; postgres_user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here, you can run Postgres queries against your database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;Starting with a blank sheet of paper can be kind of daunting, so writing (and having) basic tutorials like this to lay out some basic first steps to be a good motivational and organizational tool. I hope this has been helpful.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>docker</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Idris FizzBuzz Part IV: Main and .ipkg Files</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Fri, 19 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/idris-fizzbuzz-part-iv-main-and-ipkg-files-37dp</link>
      <guid>https://dev.to/webbureaucrat/idris-fizzbuzz-part-iv-main-and-ipkg-files-37dp</guid>
      <description>&lt;p&gt;This is the fourth and final part of a walkthrough of FizzBuzz, a common interview problem, in Idris. If you haven't read the other parts, you can &lt;a href="https://webbureaucrat.gitlab.io/articles/idris-fizzbuzz-part-i-monads-comments-assert-smaller/" rel="noopener noreferrer"&gt;start with Part I&lt;/a&gt;. To show how to import and use libraries, we're going to divide this project into a library and an executable. Along the way, we will create &lt;em&gt;.ipkg&lt;/em&gt; packages for both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Idris .ipkg files for libraries
&lt;/h3&gt;

&lt;p&gt;Start by running &lt;code&gt;idris2 --init&lt;/code&gt; in the fizzbuzz project and fill in some sensible defaults. This is what I ended up with:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;fizzbuzz.ipkg&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package fizzbuzz

authors = "eleanorofs"
brief = "a fizzbuzz example in the Idris language."
bugtracker = "https://gitlab.com/eleanorofs/idris-fizzbuzz/-/issues"
-- packages to add to search path
-- depends =
-- name of executable
-- executable =
homepage = "https://gitlab.com/eleanorofs/idris-fizzbuzz"
license = "MIT"
-- main file (i.e. file to load at REPL)
-- main =
maintainers = "eleanorofs"
-- modules to install
modules = Division, FizzBuzz
opts = "--warnpartial"
readme = "./README.md"
sourcedir = "src"
sourceloc = "https://gitlab.com/eleanorofs/idris-fizzbuzz.git"
version = 0.0.1

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

&lt;/div&gt;



&lt;p&gt;The important thing here is that &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;executable&lt;/code&gt; are not filled in because this is a library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing an Idris executable
&lt;/h3&gt;

&lt;p&gt;Now we can create a new Idris package for the executable. As before, let's start with the source.&lt;/p&gt;

&lt;p&gt;Let's recall that we have a method &lt;code&gt;numberToFBNString&lt;/code&gt; which takes a single number and returns the string FizzBuzz equivalent of the number. Now, consider how we might do that recursively for a list of numbers. One way might be to combine the numbers into a long string and then print that string, but that would result in a slow-feeling user experience for large numbers as it would take a long time to concatenate the string. Instead, let's print the numbers one at a time, using the &lt;code&gt;do&lt;/code&gt; syntax and the &lt;code&gt;IO ()&lt;/code&gt; monad.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;idris-fizzbuzz-main/src/Main.idr&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Main&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;FizzBuzz&lt;/span&gt;

&lt;span class="nf"&gt;printFizzBuzz :&lt;/span&gt; &lt;span class="kt"&gt;Vect&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;Nat &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="n"&gt;printFizzBuzz&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;putStrLn &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="n"&gt;printFizzBuzz&lt;/span&gt; &lt;span class="p"&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;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="kr"&gt;do&lt;/span&gt; &lt;span class="nb"&gt;putStrLn &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numberToFBNString&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
     &lt;span class="n"&gt;printFizzBuzz&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="c1"&gt;--recursive call on the rest of the list&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we can write a main function which calls &lt;code&gt;printFizzBuzz&lt;/code&gt; on a long vector, and we're done.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;idris-fizzbuzz-main/src/Main.idr&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Main&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Vect&lt;/span&gt; &lt;span class="c1"&gt;--imports fromList&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;FizzBuzz&lt;/span&gt;

&lt;span class="nf"&gt;printFizzBuzz :&lt;/span&gt; &lt;span class="kt"&gt;Vect&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;Nat &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="n"&gt;printFizzBuzz&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;putStrLn &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="n"&gt;printFizzBuzz&lt;/span&gt; &lt;span class="p"&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;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="kr"&gt;do&lt;/span&gt; &lt;span class="nb"&gt;putStrLn &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numberToFBNString&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
     &lt;span class="n"&gt;printFizzBuzz&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="c1"&gt;--recursive call on the rest of the list&lt;/span&gt;

&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;main :&lt;/span&gt; &lt;span class="kt"&gt;IO &lt;/span&gt;&lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;printFizzBuzz&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;fromList&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mf"&gt;1&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="mf"&gt;1000&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 &lt;code&gt;main&lt;/code&gt; is a total function! We have a strong guarantee that it will never error out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Idris &lt;em&gt;.ipkg&lt;/em&gt; files for executables
&lt;/h3&gt;

&lt;p&gt;Now run &lt;code&gt;idris2 --init&lt;/code&gt; again, but then change the values to an executable by including the main file and the executable name. Then, add your &lt;code&gt;fizzbuzz&lt;/code&gt;library as a dependency using &lt;code&gt;depends&lt;/code&gt;. You should end up with something like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;idris-fizzbuzz-main/fizzbuzz-main.ipkg&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package fizzbuzz-main
authors = "eleanorofs"
brief = "prints FizzBuzz from 1 to 1000."
license = "MIT"
maintainers = "eleanorofs"
readme = "./README.md"
-- homepage = 
-- sourceloc =
-- bugtracker =

-- packages to add to search path
depends = fizzbuzz

-- modules to install
modules = Main

-- main file (i.e. file to load at REPL)
main = Main

-- name of executable
executable = "fizzbuzz-main"
opts = "--warnpartial"
sourcedir = "src"
version = 0.0.1

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compiling and running an Idris executable
&lt;/h3&gt;

&lt;p&gt;With this configuration in place, we should be able to compile our executable with &lt;code&gt;idris2 --build fizzbuzz-main.ipkg&lt;/code&gt;. This will produce a &lt;em&gt;build&lt;/em&gt; folder. We can run the executable, then, as &lt;code&gt;./build/exec/fizzbuzz-main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You should see, well, FizzBuzz.&lt;/p&gt;

&lt;p&gt;If something isn't quite right, have a look at this Nix shell script which walks through all the steps needed to run this executable, including downloading and installing the previous FizzBuzz library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env nix-shell&lt;/span&gt;
&lt;span class="c"&gt;#! nix-shell -i bash --pure&lt;/span&gt;
&lt;span class="c"&gt;#! nix-shell -p bash cacert chez git idris2&lt;/span&gt;

&lt;span class="nb"&gt;mkdir &lt;/span&gt;dependencies
&lt;span class="nb"&gt;cd &lt;/span&gt;dependencies
git clone https://gitlab.com/eleanorofs/idris-fizzbuzz
&lt;span class="nb"&gt;cd &lt;/span&gt;idris-fizzbuzz
idris2 &lt;span class="nt"&gt;--build&lt;/span&gt; fizzbuzz.ipkg
idris2 &lt;span class="nt"&gt;--install&lt;/span&gt; fizzbuzz.ipkg
&lt;span class="nb"&gt;cd&lt;/span&gt; ../..
idris2 &lt;span class="nt"&gt;--build&lt;/span&gt; fizzbuzz-main.ipkg
./build/exec/fizzbuzz-main

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

&lt;/div&gt;



&lt;p&gt;(This is something I love about Nix--scripts themselves are not only perfectly reproducible but include self-documenting lists of dependencies.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping up FizzBuzz for Idris
&lt;/h3&gt;

&lt;p&gt;I hope this has been a useful introduction to Idris and its basic usage and syntax. This was a fun little project for me, and, if you're reading this, I hope to see what fun little projects you write in Idris, too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/eleanorofs/idris-fizzbuzz" rel="noopener noreferrer"&gt;Full source for library project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="[https://gitlab.com/eleanorofs/idris-fizzbuzz-main](https://gitlab.com/eleanorofs/idris-fizzbuzz-main)"&gt;Full source for executable project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>functional</category>
      <category>idris</category>
      <category>totality</category>
    </item>
    <item>
      <title>Idris FizzBuzz Part III: Defining Types and Importing Modules</title>
      <dc:creator>webbureaucrat</dc:creator>
      <pubDate>Wed, 10 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/webbureaucrat/idris-fizzbuzz-part-iii-defining-types-and-importing-modules-5332</link>
      <guid>https://dev.to/webbureaucrat/idris-fizzbuzz-part-iii-defining-types-and-importing-modules-5332</guid>
      <description>&lt;p&gt;This is Part III of my attempt to explain how to use the Idris programming language through a tutorial on FizzBuzz, the common software development hiring interview problem. If you're new to Idris and haven't read &lt;a href="https://webbureaucrat.gitlab.io/articles/idris-fizzbuzz-part-i-monads-comments-assert-smaller/" rel="noopener noreferrer"&gt;Part I&lt;/a&gt; and &lt;a href="https://webbureaucrat.gitlab.io/articles/idris-fizzbuzz-part-ii-maybes-infix-notation-idris-holes/" rel="noopener noreferrer"&gt;Part II&lt;/a&gt;, I recommend doing that now. This article will go over defining our own types and importing our own modules as well as recap what we've learned about case-matching and basic syntax. &lt;/p&gt;




&lt;p&gt;Just to recap, here's what we have so far:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Division&lt;/span&gt;

&lt;span class="cd"&gt;||| Returns a `Just of the remainder of two numbers, or `Nothing` if the &lt;/span&gt;
&lt;span class="cd"&gt;||| divisor is zero.&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;modulo :&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe Nat
&lt;/span&gt;&lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kt"&gt;Z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Nothing&lt;/span&gt; &lt;span class="c1"&gt;--can't divide by zero, so Nothing&lt;/span&gt;
&lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="kt"&gt;Z&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Just&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;
  &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assert_smaller&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minus&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;
  &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kc"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt;

&lt;span class="cd"&gt;||| Returns `True` if the first number divides the second evenly, otherwise &lt;/span&gt;
&lt;span class="cd"&gt;||| returns `False`. Also returns `False` if the divisor is zero. &lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;divides :&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool
&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt; &lt;span class="n"&gt;dividend&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;dividend&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;modulo&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt; 
    &lt;span class="kc"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
    &lt;span class="kc"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have completed our Divides module, which holds all of the basic arithmetic we need for our program, so now we get to work on FizzBuzz specific logic. Let's put that logic in a different module and call it FizzBuzz. &lt;/p&gt;

&lt;p&gt;When we think about what we need for FizzBuzz, one of the first things we should notice is that we're classifying numbers and specifying different behavior based on their properties. In object orientation, we might define a &lt;code&gt;Printable&lt;/code&gt; interface and have &lt;code&gt;Fizz&lt;/code&gt; &lt;code&gt;Buzz&lt;/code&gt;, &lt;code&gt;FizzBuzz&lt;/code&gt; and regular &lt;code&gt;Number&lt;/code&gt; implementations, but in Idris we can simply define a union type like so: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/FizzBuzz.idr&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FizzBuzz&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Fizz&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Buzz&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kt"&gt;Nat
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;Number&lt;/code&gt; has a &lt;code&gt;Nat&lt;/code&gt; data member just like &lt;code&gt;Just&lt;/code&gt; had a &lt;code&gt;Nat&lt;/code&gt; data member in our previous article. &lt;/p&gt;

&lt;p&gt;This is a little terse, though. We can do better. &lt;/p&gt;

&lt;h3&gt;
  
  
  Idris documentation comments in type definitions
&lt;/h3&gt;

&lt;p&gt;Recall that a comment defined with three bars (&lt;code&gt;|||&lt;/code&gt;) is a documentation comment in Idris, meaning it can show up in the Idris tooling and help the user as well as the reader of the source. Let's fix this union type up with documentation comments. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/FizzBuzz.idr&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FizzBuzz&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="nb"&gt;and &lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Fizz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;Buzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;neither&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="n"&gt;nor&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kt"&gt;Nat
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Importing modules in the Idris programming language
&lt;/h3&gt;

&lt;p&gt;Next we need a way of getting from &lt;code&gt;Nat&lt;/code&gt; numbers to &lt;code&gt;FizzBuzzNumber&lt;/code&gt;s, which means we need our &lt;code&gt;divides&lt;/code&gt; function from the previous post. To start, let's export just the &lt;code&gt;divides&lt;/code&gt; function from the &lt;code&gt;Division&lt;/code&gt; module by decorating the &lt;code&gt;divides&lt;/code&gt; function with the &lt;code&gt;export&lt;/code&gt; keyword. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/Division.idr&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Division&lt;/span&gt;

&lt;span class="cd"&gt;||| Returns a `Just of the remainder of two numbers, or `Nothing` if the &lt;/span&gt;
&lt;span class="cd"&gt;||| divisor is zero.&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;modulo :&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe Nat
&lt;/span&gt;&lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kt"&gt;Z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Nothing&lt;/span&gt; &lt;span class="c1"&gt;--can't divide by zero, so Nothing&lt;/span&gt;
&lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="kt"&gt;Z&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Just&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;
  &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assert_smaller&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minus&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;
  &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kc"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt;

&lt;span class="cd"&gt;||| Returns `True` if the first number divides the second evenly, otherwise &lt;/span&gt;
&lt;span class="cd"&gt;||| returns `False`. Also returns `False` if the divisor is zero. &lt;/span&gt;
&lt;span class="n"&gt;export&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; 
&lt;span class="nf"&gt;divides :&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool
&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt; &lt;span class="n"&gt;dividend&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;dividend&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;modulo&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt; 
    &lt;span class="kc"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
    &lt;span class="kc"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can go ahead and import the &lt;code&gt;Division&lt;/code&gt; module by using the &lt;code&gt;import&lt;/code&gt; keyword in the &lt;code&gt;FizzBuzz&lt;/code&gt; module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FizzBuzz&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Division&lt;/span&gt; &lt;span class="c1"&gt;--imports the `divides` function&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="nb"&gt;and &lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Fizz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;Buzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;neither&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="n"&gt;nor&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kt"&gt;Nat
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I went ahead and put in a comment explaining exactly what we're importing because a peculiar thing about the Idris language is that, by default, Idris exposes all &lt;code&gt;expose&lt;/code&gt;d modules. &lt;/p&gt;

&lt;p&gt;(Frankly, I'm not crazy about that as a default, so a comment is a good practice.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested conditional logic in Idris
&lt;/h3&gt;

&lt;p&gt;I admit I'm torn on using the infix notation from the previous article. I'm not crazy about filling up my code with a bunch of backticks, but for mathematical expressions where the English really lends itself to saying something like, "if 3 evenly divides n then..." I think infix makes sense.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FizzBuzz&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Division&lt;/span&gt; &lt;span class="c1"&gt;--imports the `divides` function&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="nb"&gt;and &lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Fizz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;Buzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;neither&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="n"&gt;nor&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kt"&gt;Nat
&lt;/span&gt;
&lt;span class="cd"&gt;||| Given a number, returns a Fizzbuzz representation of the number depending&lt;/span&gt;
&lt;span class="cd"&gt;||| on whether it is divisible by three, five, or both, using the `divides` &lt;/span&gt;
&lt;span class="cd"&gt;||| function from the `Division` module.&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;classify :&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt;
&lt;span class="n"&gt;classify&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;15&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 
  &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt;
  &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 
       &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;Fizz&lt;/span&gt; 
       &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;Buzz&lt;/span&gt; &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 

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

&lt;/div&gt;



&lt;p&gt;Note again that we don't have to specify &lt;code&gt;Division.divides&lt;/code&gt; in our code, though in most cases I think I would, anyway. &lt;/p&gt;

&lt;p&gt;As you can see, nested conditionals in Idris work a lot like they do in other languages, or more precisely, like the ternary (&lt;code&gt;?:&lt;/code&gt;) operators do in other languages since both clauses evaluate to the return type. &lt;/p&gt;

&lt;h3&gt;
  
  
  Converting a number to a &lt;code&gt;String&lt;/code&gt; type in Idris
&lt;/h3&gt;

&lt;p&gt;Now we can pattern match on the type &lt;code&gt;FizzBuzzNumber&lt;/code&gt; as we have before. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/FizzBuzz.idr&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FizzBuzz&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Division&lt;/span&gt; &lt;span class="c1"&gt;--imports the `divides` function&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="nb"&gt;and &lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Fizz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;Buzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;neither&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="n"&gt;nor&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kt"&gt;Nat
&lt;/span&gt;
&lt;span class="cd"&gt;||| Given a number, returns a Fizzbuzz representation of the number depending&lt;/span&gt;
&lt;span class="cd"&gt;||| on whether it is divisible by three, five, or both, using the `divides` &lt;/span&gt;
&lt;span class="cd"&gt;||| function from the `Division` module.&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;classify :&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt;
&lt;span class="n"&gt;classify&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;15&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 
  &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt;
  &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 
       &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;Fizz&lt;/span&gt; 
       &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;Buzz&lt;/span&gt; &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 

&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;fbnToString :&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"FizzBuzz"&lt;/span&gt;
&lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="kt"&gt;Fizz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Fizz"&lt;/span&gt;
&lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="kt"&gt;Buzz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Buzz"&lt;/span&gt;
&lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;show &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, for most numbers, I'm using the &lt;code&gt;show&lt;/code&gt; function, which converts a &lt;code&gt;Nat&lt;/code&gt; to a &lt;code&gt;String&lt;/code&gt; in Idris. &lt;/p&gt;

&lt;h3&gt;
  
  
  Modular encapsulation in Idris
&lt;/h3&gt;

&lt;p&gt;Clearly, we're pretty close to being able to use our &lt;code&gt;FizzBuzz&lt;/code&gt; module. It would be great, though, if we we could hide the &lt;code&gt;FizzBuzzNumber&lt;/code&gt; type entirely by &lt;code&gt;expose&lt;/code&gt;ing a function to convert a number to a FizzBuzz &lt;code&gt;String&lt;/code&gt; directly. &lt;/p&gt;

&lt;p&gt;Let's do that now: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/FizzBuzz.idr&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight idris"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FizzBuzz&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Division&lt;/span&gt; &lt;span class="c1"&gt;--imports the `divides` function&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="nb"&gt;and &lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Fizz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                      &lt;span class="kt"&gt;Buzz&lt;/span&gt; 
                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|||&lt;/span&gt; &lt;span class="kt"&gt;Represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;divisible&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;neither&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="n"&gt;nor&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
                      &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kt"&gt;Nat
&lt;/span&gt;
&lt;span class="cd"&gt;||| Given a number, returns a Fizzbuzz representation of the number depending&lt;/span&gt;
&lt;span class="cd"&gt;||| on whether it is divisible by three, five, or both, using the `divides` &lt;/span&gt;
&lt;span class="cd"&gt;||| function from the `Division` module.&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;classify :&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt;
&lt;span class="n"&gt;classify&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;15&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 
  &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt;
  &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 
       &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;Fizz&lt;/span&gt; 
       &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;divides&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;Buzz&lt;/span&gt; &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; 

&lt;span class="cd"&gt;||| Converts a `FizzBuzzNumber` value to a `String`. &lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;fbnToString :&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzzNumber&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="kt"&gt;FizzBuzz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"FizzBuzz"&lt;/span&gt;
&lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="kt"&gt;Fizz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Fizz"&lt;/span&gt;
&lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="kt"&gt;Buzz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Buzz"&lt;/span&gt;
&lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;show &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; 

&lt;span class="cd"&gt;||| Converts a `Nat` to a `String` according to the standard requirements of&lt;/span&gt;
&lt;span class="cd"&gt;||| FizzBuzz, displaying "Fizz" if the number is divisible by 3, "Buzz" if the&lt;/span&gt;
&lt;span class="cd"&gt;||| number is divisible by 5, or "Fizzbuzz" if the number is divisible by both&lt;/span&gt;
&lt;span class="cd"&gt;||| 3 and five. &lt;/span&gt;
&lt;span class="n"&gt;export&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="nf"&gt;numberToFBNString :&lt;/span&gt; &lt;span class="kt"&gt;Nat &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;numberToFBNString&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fbnToString&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classify&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;What we now have is effectively a small library that exports two functions: &lt;code&gt;Division.divides&lt;/code&gt; and &lt;code&gt;FizzBuzz.numbertoFBNString&lt;/code&gt;. In the next article, we'll set up a &lt;em&gt;.ipkg&lt;/em&gt; package file and make the function available on our system.&lt;/p&gt;

&lt;h3&gt;
  
  
  In conclusion
&lt;/h3&gt;

&lt;p&gt;In this tutorial, I hope you've learned the basics of declaring a union type and how importing modules works in Idris. Let me know if there's anything I can make any clearer. In the next module, we'll be looking at setting up our main function and trying our hands at dependent types! &lt;/p&gt;

</description>
      <category>functional</category>
      <category>idris</category>
    </item>
  </channel>
</rss>
