<?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: Anton Kiłka</title>
    <description>The latest articles on DEV Community by Anton Kiłka (@shamansir).</description>
    <link>https://dev.to/shamansir</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%2F25634%2Fcd172972-e9ed-4379-97b3-878d32a81f46.png</url>
      <title>DEV Community: Anton Kiłka</title>
      <link>https://dev.to/shamansir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shamansir"/>
    <language>en</language>
    <item>
      <title>Play: UI Layouts in PureScript</title>
      <dc:creator>Anton Kiłka</dc:creator>
      <pubDate>Sun, 11 Jan 2026 04:13:13 +0000</pubDate>
      <link>https://dev.to/shamansir/play-ui-layouts-in-purescript-1cb5</link>
      <guid>https://dev.to/shamansir/play-ui-layouts-in-purescript-1cb5</guid>
      <description>&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%2Fgrw26irxdumdpp9k3hwz.jpg" 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%2Fgrw26irxdumdpp9k3hwz.jpg" alt="row-1-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[ &lt;a href="https://pursuit.purescript.org/packages/purescript-play/" rel="noopener noreferrer"&gt;&lt;code&gt;play&lt;/code&gt; package in pursuit&lt;/a&gt; ] | [ &lt;a href="https://shamansir.github.io/Blog/blog-en/aa-2026-01-11-play-ui-layouts-in-purescript.html" rel="noopener noreferrer"&gt;original article in my blog&lt;/a&gt; ]&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Now that most of my latest projects are written in PureScript&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, my favorite language for development for several years already, I noticed that I am developing a bunch of web apps with user interfaces of different complexity:&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%2Fxsq94u8dpqw4ynkhq2ju.jpg" 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%2Fxsq94u8dpqw4ynkhq2ju.jpg" alt="noodle-svg-tree" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me list some of the details from these examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Noodle — visual programming platform, where:

&lt;ul&gt;
&lt;li&gt;it is possible to open many side panels: documentation, action history, log, and so on;&lt;/li&gt;
&lt;li&gt;there is a library of node families; &lt;/li&gt;
&lt;li&gt;there as well is status bar with several cells;&lt;/li&gt;
&lt;li&gt;there is patch area where all the nodes are layed out;&lt;/li&gt;
&lt;li&gt;and all the nodes have their own structure which I want to have modular;

&lt;ul&gt;
&lt;li&gt;the node could be vertical: inlets on the top, outlets on the bottom;&lt;/li&gt;
&lt;li&gt;the node could be horizontal: inlets on the left, outlets on the right;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;there are several stacked layers: canvas in the background, SVG main area as a layer in the middle, HTML layer on top, and recently I have added one more canvas on top for the node bodies;&lt;/li&gt;

&lt;li&gt;not to mention that to find a free space for a new node, we could also need a smart layouting system intended just for nodes;&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&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%2Fzkj9g0qn4j65v9r5fbr0.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%2Fzkj9g0qn4j65v9r5fbr0.png" alt="noodle-1" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/shamansir/noodle" rel="noopener noreferrer"&gt;Noodle at Github&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Tree graph explorer, to visualize the many kinds of tree-structured data I have; Sometimes I store UI dependencies in a graph, sometimes I keep my book library organized as a tree, where a shelf or an author's name first letters can represent a node; It has these optional panels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The tree itself;&lt;/li&gt;
&lt;li&gt;The pinned nodes area, to keep an eye on the specific tree nodes (they can be complex interactive components by themselves);&lt;/li&gt;
&lt;li&gt;The area where I can see a tree in its plain representation for easier navigation, where the selected nodes are highlighted;&lt;/li&gt;
&lt;li&gt;The history of the visited paths, so I would be able to return to them later;&lt;/li&gt;
&lt;li&gt;Current location and current selection, since it is heavily based on keyboard navigation;&lt;/li&gt;
&lt;li&gt;Zoom panel;&lt;/li&gt;
&lt;li&gt;The export area, for JSON and other formats preview;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&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%2Fs5pjtbghqmv7y2xiqnoa.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%2Fs5pjtbghqmv7y2xiqnoa.png" alt="svg-tree" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...and counting. I also plan to revive some older projects, and they also have many panels and subpanels. So I felt an acute need to ease the calculation of all the positioning, because for every small part the position needs to be calculated and I want them responsive. And with PureScript we're not having Swift UI-like constructors... yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/shamansir/purescript-yoga-tree-svg" rel="noopener noreferrer"&gt;SVG Tree at Github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Clay UI as an inspiration
&lt;/h2&gt;

&lt;p&gt;Almost in the same moments when this need was most desperate in my mind, YouTube happened to suggest me the video about Clay UI : the UI layouting library for C++ with beautifully simple and consice algorithm (yes, in C++) and it was all explained in all details in full in 40 minutes.&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%2Fa5xlz7259cuf3e2tblne.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%2Fa5xlz7259cuf3e2tblne.png" alt="clay-ui-video-screen" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=by9lQvpvMIc" rel="noopener noreferrer"&gt;How Clay's UI Layout Algorithm Works by Nic Barker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I was definitely inspired, I love to discover the easier parts in what was considered complex before, and O decided to translate this algorithm to pure FP version, of course it turned out to be an interesting thought-trainer by itself, and considering the problems I mentioned above, the challenge, when resolved, tended to grow very helpful and useful for my cause.&lt;/p&gt;

&lt;p&gt;While C++ code is usually imperative, pure FP seem to require the completely perpendicular approach... partly it is true, the code is very different, but Nic, the author of Clay UI is so talented that his ideas are universal for almost any programming approach, and they could be layed out over FP concepts like one would considered they were there from the start, we have folding and recursion out of the box for our help, but the order of steps and mathematics are the same: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* fit sizing reverse-breadth-first (from leaves to the root);
* then calculate grow sizing breadth-first (from the root to the leaves);
* then apply positions having the sizes already (in any direction);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;NB: It is worth mentioning that one of the core features of Clay is measuring text size in any font, so that it can be layed out correctly. In C++ it is an uncommon but needed feature, but in front-end web development we have our own ways for that: nowadays browser engines help us, but not a long time ago we had to pre-render the text in some HTML element that is invisible to the user and measuring it. So I decided to omit this part, which is probably better to implement through JavaScript FFI.    &lt;/p&gt;

&lt;p&gt;I can't say that it was &lt;em&gt;very&lt;/em&gt; easy, but still it was much was easier than I expected, to implement all this logic. And it also turned out to be just &lt;a href="https://github.com/shamansir/purescript-play/blob/main/src/Play/Layout.purs#L27" rel="noopener noreferrer"&gt;around 300 lines of code&lt;/a&gt;, even including empty lines, documentation and type definitions. I planned to use Claude/Copilot only on the last stages for writing the tests and clarifying the algorithm with documentation, and indeed I did enable it only after implementing the core part, but in the end we developed the UI Constructor as well as some quick encoding system for layouts together, and also AI helped me later with fixing some hardly noticable issues regarding children alignment and percentage positioning in deeper structures. &lt;/p&gt;

&lt;p&gt;The UI of the constructor is a bit bulky, there are many inline CSS styles there, but there are many features that could help you draft or build your layout beforehand, and generate the code to fill it in with the values later.&lt;/p&gt;

&lt;p&gt;...And I named the library Play, because no other word came to my mind in attempts to combine PureScript and Clay. Also, I suppose with Japanese pronounciation of this word could sound very similar to "Pure". ChatGPT, do you know any better? Picklay? Purée? Hooray?...&lt;/p&gt;

&lt;p&gt;...Hey, may you would like to have some fun already, so there is a beforementioned layout constructor for you to &lt;em&gt;play&lt;/em&gt; with: &lt;a href="https://shamansir.github.io/purescript-play/constructor.html" rel="noopener noreferrer"&gt;https://shamansir.github.io/purescript-play/constructor.html&lt;/a&gt;&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%2Fww3pbdg11niwahn42qsg.jpg" 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%2Fww3pbdg11niwahn42qsg.jpg" alt="row-2-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Play API
&lt;/h2&gt;

&lt;p&gt;The idea is to let user fill in a polymorphic parameter &lt;code&gt;a&lt;/code&gt; with any type they want: &lt;code&gt;Play a&lt;/code&gt; can be &lt;code&gt;Play Int&lt;/code&gt;, &lt;code&gt;Play String&lt;/code&gt;, &lt;code&gt;Play Color&lt;/code&gt;, &lt;code&gt;Play UIPart&lt;/code&gt;, &lt;code&gt;Play Key&lt;/code&gt;, &lt;code&gt;Play Character&lt;/code&gt;,  &lt;code&gt;Play Sonet&lt;/code&gt;, &lt;code&gt;Play HalfLife3UI&lt;/code&gt;, &lt;code&gt;Play (Play Whatever)&lt;/code&gt;...&lt;/p&gt;

&lt;p&gt;PureScript allows you to define almost any operator you want, so I decided to have &lt;code&gt;~*&lt;/code&gt; for chaining, which is actually just an alias for &lt;code&gt;#&lt;/code&gt;, so you can use any you prefer, just don't mix them in the same code. Here's the example of a defintion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;MenuItem&lt;/span&gt;
   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Root&lt;/span&gt;
   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Title&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Icon&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;ClayMenu&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Root&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Item&lt;/span&gt; &lt;span class="kt"&gt;MenuItem&lt;/span&gt;

&lt;span class="n"&gt;menuItem&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt; &lt;span class="kt"&gt;ClayMenu&lt;/span&gt;
&lt;span class="n"&gt;menuItem&lt;/span&gt; &lt;span class="n"&gt;itemTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Item&lt;/span&gt; &lt;span class="kt"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightFit&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leftToRight&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Title&lt;/span&gt; &lt;span class="n"&gt;itemTitle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="mf"&gt;60.0&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Item&lt;/span&gt; &lt;span class="kt"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="mf"&gt;60.0&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="mf"&gt;60.0&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="n"&gt;menuDef&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt; &lt;span class="kt"&gt;ClayMenu&lt;/span&gt;
&lt;span class="n"&gt;menuDef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;Root&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="mf"&gt;250.0&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightFit&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;topToBottom&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;childGap&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;menuItem&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; 
                        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;"Copy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Paste"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Spell Check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Dictionary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Comment"&lt;/span&gt; &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Example&lt;/span&gt; &lt;span class="kt"&gt;ClayMenu&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;You can find the examples &lt;a href="https://github.com/shamansir/purescript-play/tree/main/test/Demo/Examples" rel="noopener noreferrer"&gt;in the sources&lt;/a&gt; of the Constructor as well as &lt;a href="https://github.com/shamansir/purescript-play/blob/main/test/Test/Spec/Layout.purs" rel="noopener noreferrer"&gt;in the test spec&lt;/a&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt;, there should be a fitting one for almost any case! :)&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%2F790pgtxsgqxd42zjvk0h.jpg" 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%2F790pgtxsgqxd42zjvk0h.jpg" alt="row-3-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Play&lt;/code&gt; Types and Functions
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Play a&lt;/code&gt; contains all the layout definitions, which side of the container / cell is fixed in size, or grows, or if it fits its children (more on that later), but they are not layed out yet (don't lay off, better lay out!).&lt;/p&gt;

&lt;p&gt;For that, there's &lt;code&gt;Layout a&lt;/code&gt;, which, as you may suggest, stores all the items layed out strictly following these definitions, having their positions and dimensions calculated.&lt;/p&gt;

&lt;p&gt;So, when you have defined the logic of how your UI parts fit and grow, call the &lt;code&gt;layout&lt;/code&gt; function, which is a verb in this case, and you'll have the calculated rectangles in place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;menuLayout&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Layout&lt;/span&gt; &lt;span class="kt"&gt;ClayMenu&lt;/span&gt;
&lt;span class="n"&gt;menuLayout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="n"&gt;menuDef&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since, as you may have noticed, I really like tree structures, both of those are just trees under the hood:&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;type&lt;/span&gt; &lt;span class="kt"&gt;WithDef&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Def&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;WithDefRect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Def&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Rect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;WithDef&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Layout&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Layout&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;WithDefAndRect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Layout&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toTree&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layoutTree&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Layout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Def&lt;/code&gt; is just the configuration, while &lt;code&gt;Rect&lt;/code&gt; contains both position and size of every element. You may convert the &lt;code&gt;Layout a&lt;/code&gt; to either a tree or a flattened array, what is better fits your needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;layoutToTree&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Layout&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;WithRect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;flattenLayout&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Layout&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;WithRect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The calculations are already made, so the order is not important anymore, all the positions and dimensions are there, so you lose nothing even with a flat array, you may just map over it in the UI renderer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt; 
    &lt;span class="n"&gt;windowSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
    &lt;span class="n"&gt;myLayout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;myUI&lt;/span&gt; &lt;span class="n"&gt;windowSize&lt;/span&gt; &lt;span class="c1"&gt;-- your layout could depend on the window size, but it's not obligatory;&lt;/span&gt;
&lt;span class="kr"&gt;in&lt;/span&gt; 
    &lt;span class="kt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; 
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Position&lt;/span&gt; &lt;span class="kt"&gt;Relative&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;renderItem&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flattenLayout&lt;/span&gt; &lt;span class="n"&gt;myLayout&lt;/span&gt;
    &lt;span class="kr"&gt;where&lt;/span&gt; 
        &lt;span class="n"&gt;renderItem&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;PT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;WithDefAndRect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;
        &lt;span class="n"&gt;renderItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
            &lt;span class="kt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; 
              &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Position&lt;/span&gt; &lt;span class="kt"&gt;Absolute&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Top&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- I usually use SVG so I translate `Svg.g [] [...]` to the position&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;v&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt; 
                  &lt;span class="kt"&gt;Root&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
                  &lt;span class="kt"&gt;Item&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Title&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
                  &lt;span class="kt"&gt;Item&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Icon&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; 


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

&lt;/div&gt;



&lt;p&gt;If you need to keep parent-child relations for something else, I recommend prefer using &lt;code&gt;Play a&lt;/code&gt; structure over &lt;code&gt;Layout a&lt;/code&gt;, however once again those both are just &lt;code&gt;Tree a&lt;/code&gt; in disguise.&lt;/p&gt;

&lt;p&gt;So, once more, this &lt;code&gt;a&lt;/code&gt; can be anything, for example in case of Noodle node inner layout I have &lt;code&gt;Play NodePart&lt;/code&gt; where &lt;code&gt;NodePart&lt;/code&gt; is defined this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;NodePart&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Background&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Title&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;BodyBg&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;BodyContent&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Inlets&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Outlets&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Inlet&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;InletName&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;InletConnector&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Outlet&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;OutletName&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;OutletConnector&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Buttons&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Button&lt;/span&gt; &lt;span class="kt"&gt;Remove&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Button&lt;/span&gt; &lt;span class="kt"&gt;Collapse&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may find even more examples later in the post.&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%2Ffjosexneag1tjvjv7mtr.jpg" 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%2Ffjosexneag1tjvjv7mtr.jpg" alt="row-4-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Layout definition
&lt;/h3&gt;

&lt;p&gt;So, here's how you can define your layout:&lt;/p&gt;

&lt;p&gt;Any cell can have its orientation either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Horizontal&lt;/em&gt; / &lt;em&gt;LeftToRight&lt;/em&gt; — width is the main axis, the children are aligned horizontally;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Vertical&lt;/em&gt; / &lt;em&gt;TopToBottom&lt;/em&gt; — height is the main axis, the children are aligned vertically;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;ZAxis&lt;/em&gt; / &lt;em&gt;BackToFront&lt;/em&gt; - yes, just like the layered cake, I really wanted to have this in some particular cases so I implemented it as well;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, either width or height of any cell can either be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Fixed&lt;/em&gt; to some exact pixel size;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Fit&lt;/em&gt; its children by this side: pack them and resize to the sum of their width or height;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Percentage&lt;/em&gt; amount of the corresponding side of its parent, overflow is allowed and cut by the rectangle of the parent;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Grow&lt;/em&gt;, unless it meets the next child or its parent can not expand more on the right / to the bottom;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;FitGrow&lt;/em&gt; — fit its children and only then grow to the right / to the bottom;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;FitMin&lt;/em&gt; — fit the children but no less than given value in pixels, so if children take less requested space, the side will have this size anyway, otherwise it will fit them into a larger size;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;FitMax&lt;/em&gt; — same, but no more than given value in pixels;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;FitMinMax&lt;/em&gt; — if the children fit between the given range, use the actual value, or restrict it with the given bounds;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;GrowMin&lt;/em&gt; - grow only if there's a minimum of space, else have this side zero;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is an additional configuration possible for any cell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Children Gap&lt;/em&gt; — constant space inserted between children;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Padding&lt;/em&gt; — padding on the inner sides of the cell, so that there is a space between the border and its children, can be a specific value for each side;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Alignment&lt;/em&gt; - how the children are aligned inside the cell if their size is smaller on the side of alignment, could be specified both horizontally (Left / Center / Right) and vertically (Top / Middle / Bottom); &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of &lt;code&gt;Play&lt;/code&gt; and &lt;code&gt;Layout&lt;/code&gt; are functors and applicatives:&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;type&lt;/span&gt; &lt;span class="kt"&gt;MyItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;textColor&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Color&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="n"&gt;myUI&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt; &lt;span class="kt"&gt;MyItem&lt;/span&gt;
&lt;span class="n"&gt;myUI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;....&lt;/span&gt;

&lt;span class="n"&gt;jsonTree&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt; &lt;span class="kt"&gt;Json&lt;/span&gt;
&lt;span class="n"&gt;jsonTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toJson&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;myUI&lt;/span&gt;

&lt;span class="n"&gt;positionedLabels&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Layout&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;positionedLabels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="n"&gt;myUI&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fnjvncrd2ttii25v9fy40.jpg" 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%2Fnjvncrd2ttii25v9fy40.jpg" alt="row-5-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Constructor
&lt;/h2&gt;

&lt;p&gt;Together with Claude, we've developed for you &lt;a href="https://shamansir.github.io/purescript-play/constructor.html" rel="noopener noreferrer"&gt;the Constructor&lt;/a&gt; which can ease creating layouts by making it visual instead of just code:&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%2Fy4ldxclfu9aevgg4yigi.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%2Fy4ldxclfu9aevgg4yigi.png" alt="noodle-node-example-full-screen-with-tree-root" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be not that easy to use though, however at least  we tried! :). There are several useful features we implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full properties editor:

&lt;ul&gt;
&lt;li&gt;You may change any layout parameter of a cell;&lt;/li&gt;
&lt;li&gt;Manage their children: add or remove them;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Navigate over the tree:

&lt;ul&gt;
&lt;li&gt;By clicking on the cell in the example preview;
&lt;/li&gt;
&lt;li&gt;Using the buttons on the top of the properies editor;&lt;/li&gt;
&lt;li&gt;In the Tree viewer, by clicking on the title of the item;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;View the Tree interactively:

&lt;ul&gt;
&lt;li&gt;You may collapse and expand branches in the Tree Viewer;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Convert the layout:

&lt;ul&gt;
&lt;li&gt;to PureScript code as &lt;code&gt;Play String&lt;/code&gt;, so that you can just copy-paste it when your layout is ready;&lt;/li&gt;
&lt;li&gt;to JSON definition;&lt;/li&gt;
&lt;li&gt;to YAML definition;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Optional encoded sizing labels can help in debugging (however, if the item is in the background, you can't see them);&lt;/li&gt;

&lt;li&gt;No dark mode (&lt;em&gt;yet&lt;/em&gt;);&lt;/li&gt;

&lt;li&gt;The selected example is stored in the URL;&lt;/li&gt;

&lt;li&gt;Kinda illustrates responsiveness of the layouts when you change the size of the root element...;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By enabling encoded sizing labels, you may get visual help on how your layout is structured.&lt;/p&gt;

&lt;p&gt;Start with the &lt;em&gt;Blank UI&lt;/em&gt; example if you would like to experiment from scratch.&lt;/p&gt;

&lt;p&gt;You can click blocks on the visual preview to edit their properties. Or, especially for the cases when the block is zero-size or hidden below being compltely covered by its children, you can  navigate using the Properties panel. For every child there is &lt;em&gt;Go&lt;/em&gt; button to switch to this child, and whene you're there, there are &lt;em&gt;Parent&lt;/em&gt; (which allows you to switch to the parent of this particular child) and &lt;em&gt;Root&lt;/em&gt; (which allows you to switch to the only one parent for all this layout) buttons. If they are both disabled, you're already at root. If &lt;em&gt;Parent&lt;/em&gt; is disabled, then you're on the top level.&lt;/p&gt;

&lt;p&gt;There's another, third way, to navigate: If you open the &lt;em&gt;Code &amp;amp; Tree&lt;/em&gt; panel on the bottom side of the screen, there's a tab with fully navigatable tree. Just click on any leaf and there you have switched to it.&lt;/p&gt;

&lt;p&gt;The first tab on this panel, &lt;em&gt;Code&lt;/em&gt;,  contains the generated code for current layout. &lt;/p&gt;

&lt;p&gt;Both tree view and code are instantly updated whenever you change something in the layout. Same way as the visual preview, obviously :).&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%2Fxyh2kiiruobhw46zi7xe.jpg" 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%2Fxyh2kiiruobhw46zi7xe.jpg" alt="row-6-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Algorithm
&lt;/h2&gt;

&lt;p&gt;At first I wanted to explain here &lt;a href="https://github.com/shamansir/purescript-play/blob/main/src/Play/Layout.purs#L27" rel="noopener noreferrer"&gt;the algorithm&lt;/a&gt; in the very detail, but I really tried to make it self-explanatory and I hope I succeeded, however it could still be the topic for another article.&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%2F4inixecywcxnmtag0a96.jpg" 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%2F4inixecywcxnmtag0a96.jpg" alt="row-7-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;You could've been bored enough to this point, so I decided to give you more examples and illustrate them with Kanji structure.&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%2Fkkv0bja9kvgur5bgsgje.jpg" 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%2Fkkv0bja9kvgur5bgsgje.jpg" alt="row-8-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Kanji
&lt;/h3&gt;

&lt;p&gt;Kanji are japanese hieroglyphs and they can be recursive in a sense: they can be treated as a single whole characters or contain other kanji characters inside and still be treated as a whole. But &lt;a href="https://www.laits.utexas.edu/japanese/joshu/kanji/kanji_radicals/radicals3.html" rel="noopener noreferrer"&gt;there are&lt;/a&gt; &lt;a href="https://www.kanjijump.com/browse/components" rel="noopener noreferrer"&gt;only a few certain ways&lt;/a&gt; to lay them out: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;single character;&lt;/li&gt;
&lt;li&gt;top to bottom; no matter if there are two or three elements, the above element could be smaller than the element below it or vise versa; may be the middle element is in most cases larger than the others, because other way it wouldn't be beautiful and would be weird, and kanji are nothing about weird; &lt;/li&gt;
&lt;li&gt;left to right; the left element could be smaller than the right one or vise 
versa, the same statements as for vertical axis could apply here;&lt;/li&gt;
&lt;li&gt;enclosing: where one larger element contains another smaller one and either wraps it around completely or wraps it at least from two connected sides;&lt;/li&gt;
&lt;/ul&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%2F3ytg3ma05bihszhnfj4p.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%2F3ytg3ma05bihszhnfj4p.png" alt="kanji-radicals" width="800" height="1734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.laits.utexas.edu/japanese/joshu/kanji/kanji_radicals/radicals3.html" rel="noopener noreferrer"&gt;Image Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It could be quite easy to implement, but languages and writing systems are a bit more natural than mathematical, so they tend to be unpredictable and suprising more often than solving an equation or proving a theorem. But always beatiful. As how leaves are disordered on the tree. Or may be there's pure order we aren't aware about, in search of this order we developed fractals or Wave Function Collapse algorithm or Neural Networks...&lt;/p&gt;

&lt;p&gt;So the laying out process of the kanji could repeat some times, there could be enclosing of one element inside another and then this enclosing could be &lt;br&gt;
attached to the left of other two elements.&lt;sup id="fnref3"&gt;3&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The element of kanji that can be reused inside other characters is called &lt;em&gt;radical&lt;/em&gt;. Not all of dozens of thousands kanji can be radicals, but only around 214. If we follow the book, then the number is exactly 214.&lt;/p&gt;

&lt;p&gt;Becase Unicode tries to cover all the writing systems and tries to optimize the rendering algorithms whenever possible by finding the patterns of possible combinations of characters, they developed the system called &lt;a href="https://en.wikipedia.org/wiki/Ideographic_Description_Characters" rel="noopener noreferrer"&gt;IDS&lt;/a&gt;:&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%2Fe4plu6mcos3sr1hy82ez.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%2Fe4plu6mcos3sr1hy82ez.png" alt="uncode-ids-example" width="599" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It defines all the possible known ways of combining radicals by doing what we love to do in functional programming: binary or ternary operators/functions are applied to the results of the calls of another operators/functions, and the arguments of these functions are the forementioned radicals.&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%2Fx4id9bwzbikxezeg1cw6.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%2Fx4id9bwzbikxezeg1cw6.png" alt="uncode-ids-logic-example" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codeberg.org/tonton-pixel/unicopedia-sinica" rel="noopener noreferrer"&gt;Image Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we plan to stretch radicals in different ways and not always proportionally, for rendering we'll use the slabby font instead of a caligraphic one, or else the beauty will be completely broken.&lt;/p&gt;

&lt;p&gt;Here's a separate page with all &lt;a href="https://shamansir.github.io/purescript-play/kanji.html" rel="noopener noreferrer"&gt;the examples of these Kanji&lt;/a&gt; rendered using Play UI:&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%2F12qckgtwxs1k3ehn9jcb.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%2F12qckgtwxs1k3ehn9jcb.png" alt="kanji-all" width="400" height="1462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So lets finally define what we know with the code, our implementation would mirror the IDS machine, if you want, you make take a look at &lt;a href="https://github.com/shamansir/purescript-play/blob/main/test/Demo/Examples/Kanji.purs" rel="noopener noreferrer"&gt;the actual code behind this page&lt;/a&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;newtype&lt;/span&gt; &lt;span class="kt"&gt;KanjiPart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;KanjiP&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="c1"&gt;-- we store the radical char here&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;KanjiOp&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Single&lt;/span&gt; &lt;span class="kt"&gt;KanjiPart&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;LeftToRight&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;KanjiOp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;KanjiOp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;TopToBottom&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;KanjiOp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;KanjiOp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Surround&lt;/span&gt;
        &lt;span class="kt"&gt;SurroundKind&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;inside&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;KanjiOp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;surround&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;KanjiOp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;rateX&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rateY&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;   


&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;SurroundKind&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Full&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;FromAbove&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;FromBelow&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;FromLeft&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;FromRight&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;FromUpperLeft&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;FromUpperRight&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;FromLowerLeft&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Inbetween&lt;/span&gt;         
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference is that we also remember the rate — the proportion between how much more one radical takes than its pair in a space of &lt;code&gt;1.0&lt;/code&gt;. To represent a kanji as triplets, we'll just add a pair to an element, like in pure FP. Oh wait...&lt;/p&gt;

&lt;p&gt;So now we have a universal recursive function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;toPlaySpecAt&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;KanjiOp&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt; &lt;span class="kt"&gt;KanjiItem&lt;/span&gt;
&lt;span class="n"&gt;toPlaySpecAt&lt;/span&gt; &lt;span class="n"&gt;posKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
    &lt;span class="kt"&gt;Single&lt;/span&gt; &lt;span class="n"&gt;kanji&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="kt"&gt;LeftToRight&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="kt"&gt;TopToBottom&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="kt"&gt;Surround&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;inside&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;surround&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;rateX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rateY&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The snippets below are the parts of this function. You may find these examples separately in the constructor, just look for the ones titled &lt;em&gt;Kanji Example ...&lt;/em&gt;: &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%2Fk18vcj103h62xkzp3smi.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%2Fk18vcj103h62xkzp3smi.png" alt="kanji-example" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Kanji. A single sole character / radical:
&lt;/h4&gt;

&lt;p&gt;The definition for a single character is as easy as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;AKanji&lt;/span&gt; &lt;span class="n"&gt;kanji&lt;/span&gt; &lt;span class="n"&gt;posKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
        &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightGrow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Kanji. Two (or more) characters aside:
&lt;/h4&gt;

&lt;p&gt;When we need to position two sub-parts together, we need to decide how they share the space, usually one dominates over the other:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;OpRoot&lt;/span&gt; &lt;span class="kt"&gt;OpLeftToRight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightGrow&lt;/span&gt;
    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leftToRight&lt;/span&gt;
    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;toPlaySpecAt&lt;/span&gt; &lt;span class="kt"&gt;KLeft&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthPercent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightGrow&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toPlaySpecAt&lt;/span&gt; &lt;span class="kt"&gt;KRight&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthPercent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightGrow&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Kanji. Two (or more) characters above each other:
&lt;/h4&gt;

&lt;p&gt;It's the same as with horizontal axis, but vertical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;OpRoot&lt;/span&gt; &lt;span class="kt"&gt;OpTopToBottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightGrow&lt;/span&gt;
    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;topToBottom&lt;/span&gt;
    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;toPlaySpecAt&lt;/span&gt; &lt;span class="kt"&gt;KTop&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightPercent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toPlaySpecAt&lt;/span&gt; &lt;span class="kt"&gt;KBottom&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightPercent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rate&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;h4&gt;
  
  
  Kanji. The enclosure:
&lt;/h4&gt;

&lt;p&gt;This one is a bit more complicated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt;
    &lt;span class="n"&gt;insidePlay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toPlaySpecAt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;KInside&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;inside&lt;/span&gt;
    &lt;span class="n"&gt;surroundPlay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toPlaySpecAt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;KSurround&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;surround&lt;/span&gt;
    &lt;span class="n"&gt;construct&lt;/span&gt; &lt;span class="n"&gt;alignHorz&lt;/span&gt; &lt;span class="n"&gt;alignVert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;OpRoot&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;OpSurround&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightGrow&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backToFront&lt;/span&gt;
            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;surroundPlay&lt;/span&gt;
                &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;Stub&lt;/span&gt;
                    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthGrow&lt;/span&gt;
                    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightGrow&lt;/span&gt;
                    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="n"&gt;alignHorz&lt;/span&gt;
                    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="n"&gt;alignVert&lt;/span&gt;
                    &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;
                        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;OpRoot&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;OpSurroundInside&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widthPercent&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rateX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heightPercent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rateY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="o"&gt;~*&lt;/span&gt; &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;insidePlay&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="kr"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
    &lt;span class="kt"&gt;Full&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignCenter&lt;/span&gt;    &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignMiddle&lt;/span&gt;
    &lt;span class="kt"&gt;FromAbove&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignCenter&lt;/span&gt;    &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignBottom&lt;/span&gt;
    &lt;span class="kt"&gt;FromLeft&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignRight&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignMiddle&lt;/span&gt;
    &lt;span class="kt"&gt;FromRight&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignLeft&lt;/span&gt;      &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignMiddle&lt;/span&gt;
    &lt;span class="kt"&gt;FromBelow&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignCenter&lt;/span&gt;    &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignTop&lt;/span&gt;
    &lt;span class="kt"&gt;FromUpperLeft&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignRight&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignBottom&lt;/span&gt;
    &lt;span class="kt"&gt;FromUpperRight&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignLeft&lt;/span&gt;      &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignBottom&lt;/span&gt;
    &lt;span class="kt"&gt;FromLowerLeft&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignRight&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignTop&lt;/span&gt;
    &lt;span class="kt"&gt;Inbetween&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;construct&lt;/span&gt;     &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignCenter&lt;/span&gt;    &lt;span class="kt"&gt;Play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alignTop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F25fphe6fff2cuwg2bu0b.jpg" 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%2F25fphe6fff2cuwg2bu0b.jpg" alt="row-9-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Riichi mahjong table
&lt;/h3&gt;

&lt;p&gt;As you may have noticed, Japanese culture inspires truly inspires people, so let's stick with it a bit more. There is a tabletop game called &lt;a href="https://en.wikipedia.org/wiki/Japanese_mahjong" rel="noopener noreferrer"&gt;&lt;em&gt;Riichi Mahjong&lt;/em&gt;&lt;/a&gt; in Japan, of which can think of something like Poker card game variation (what was earlier?), but the all the cards are made from dragon teeth rather than paper.&lt;/p&gt;

&lt;p&gt;You may have noticed people playing in in some Cyberpunk movies or &lt;em&gt;Umbrella Academy&lt;/em&gt; TV series or somewhere else... I am lazily trying to learn the rules already for more than a year (a perfect game for playing in Corona times with your household), for example with the help of &lt;a href="https://www.youtube.com/watch?v=hlnC2rgIPrc" rel="noopener noreferrer"&gt;this three-hour-long video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I decided that it could also be fun to lay out the table for the game. There are many variants of Mahjong games for your phone now, but be aware, it could be a casino-like experience:&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%2F99jor7ffklcjxf4jiyk5.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%2F99jor7ffklcjxf4jiyk5.png" alt="mahjong-table-inspiration" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=mUYQyUa2PoU" rel="noopener noreferrer"&gt;Source of the image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I decided that I would like to implement the layout of the table from Nintendo Switch &lt;em&gt;51 Worldwide Classics&lt;/em&gt;: &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%2Fy5u4dbwuckl3x638z8m0.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%2Fy5u4dbwuckl3x638z8m0.png" alt="mahjong-table-inspiration-2" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=tvQiCNnLC8k" rel="noopener noreferrer"&gt;Source of the image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my case it's not that beautiful and not 3D but the positions are there:&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%2F903zpv1b9nk5bb3b9vgq.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%2F903zpv1b9nk5bb3b9vgq.png" alt="mahjong-example-full-screen-2" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's where &lt;em&gt;BackToFront&lt;/em&gt; direction and percentage fitting helped a lot, because there are many parts that is easier to implement when they overlap each other. It would be an insidious move of mine if I would include the full code of this layout (even considering that it is woven from several reusable functions), so I will just leave the link to the source code for you: &lt;a href="https://github.com/shamansir/purescript-play/blob/main/test/Demo/Examples/RiichiMahjong.purs" rel="noopener noreferrer"&gt;The Riichi Mahjong Table layout&lt;/a&gt;&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%2Fmp0k1gl5tp4y85sdh4ls.jpg" 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%2Fmp0k1gl5tp4y85sdh4ls.jpg" alt="row-11-inverted" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SVG Tree Viewer
&lt;/h3&gt;

&lt;p&gt;Let the last example be a more laconic code, so here's the mentioned SVG Tree editor layout ( &lt;a href="https://github.com/shamansir/purescript-play/blob/main/test/Demo/Examples/SvgTree.purs" rel="noopener noreferrer"&gt;source code&lt;/a&gt; ): &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%2Fy8kufv15210qh0axuj6z.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%2Fy8kufv15210qh0axuj6z.png" alt="svg-tree-layout-example" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;With this article I hope to attract more attention to the languages like &lt;a href="https://www.purescript.org/" rel="noopener noreferrer"&gt;PureScript&lt;/a&gt;, or &lt;a href="https://www.unison-lang.org/" rel="noopener noreferrer"&gt;Unison&lt;/a&gt; or &lt;a href="https://lean-lang.org/" rel="noopener noreferrer"&gt;LEAN&lt;/a&gt;, or &lt;a href="https://www.haskell.org/" rel="noopener noreferrer"&gt;Haskell&lt;/a&gt; or &lt;a href="https://elm-lang.org/" rel="noopener noreferrer"&gt;Elm&lt;/a&gt; and its descendants, because they not only bring mathematical beauty in the world (I say it from the position of the guy who totally didn't like maths at school, though gladly read books from Martin Gardner or Lewis Carroll &lt;a href="https://en.wikipedia.org/wiki/The_Game_of_Logic" rel="noopener noreferrer"&gt;about Logic&lt;/a&gt;), but also the code written using them is stable, easy to reason, and brings joy.&lt;/p&gt;




&lt;p&gt;be confused with a kind of non-lazy Haskell for web development;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;which is (I please you) not to be confused with TypeScript, but rather  ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;notice that for the tests specs I developed the quick encoding of the layout parameters (which is itself covered with tests), this kind of encoding is also shown in the constructor, and if you find it useful, you are free to use it! ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;some more resources about kanji: ↩&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kanjiheatmap.com/" rel="noopener noreferrer"&gt;https://kanjiheatmap.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jd4gd.com/kanji_components.html" rel="noopener noreferrer"&gt;https://jd4gd.com/kanji_components.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kanjisense.com/browse/atomic-components" rel="noopener noreferrer"&gt;https://kanjisense.com/browse/atomic-components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cnblogs.com/Stareven233/p/18782825" rel="noopener noreferrer"&gt;https://www.cnblogs.com/Stareven233/p/18782825&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeberg.org/tonton-pixel/unicopedia-sinica" rel="noopener noreferrer"&gt;https://codeberg.org/tonton-pixel/unicopedia-sinica&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.lingodeer.com/kanji-radicals/" rel="noopener noreferrer"&gt;https://blog.lingodeer.com/kanji-radicals/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sljfaq.org/afaq/encodings.html" rel="noopener noreferrer"&gt;https://www.sljfaq.org/afaq/encodings.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://magazeta.com/cjk-and-unicode" rel="noopener noreferrer"&gt;https://magazeta.com/cjk-and-unicode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>purescript</category>
      <category>functional</category>
      <category>ui</category>
      <category>layouts</category>
    </item>
    <item>
      <title>PureScript: UI driven by Finite State Machines and Event Streams, Part II: The Example</title>
      <dc:creator>Anton Kiłka</dc:creator>
      <pubDate>Thu, 23 Apr 2020 09:42:57 +0000</pubDate>
      <link>https://dev.to/shamansir/purescript-ui-driven-by-finite-state-machines-and-event-streams-part-ii-the-example-3m77</link>
      <guid>https://dev.to/shamansir/purescript-ui-driven-by-finite-state-machines-and-event-streams-part-ii-the-example-3m77</guid>
      <description>&lt;p&gt;Just to recall, &lt;a href="https://dev.to/shamansir/purescript-ui-driven-by-finite-state-machines-and-event-streams-994"&gt;in the first part&lt;/a&gt; we are discussing using the Finite State Machines for UI with the possibility to collect errors, the ability to rollback to the last successful state, and created using Event Streams, and this is the second part with the actual practical example.&lt;/p&gt;

&lt;p&gt;To give you a nice example other than a shopping cart or ATM, let’s recall the game of Animal Crossing: New Horizons. If you haven’t played it, you most probably heard about it nowadays, but it’s not important since I will describe the scheme anyway and there should be no huge spoilers. &lt;/p&gt;

&lt;p&gt;First, the complete source code. It’s here: &lt;a href="https://github.com/shamansir/purescript-fsm" rel="noopener noreferrer"&gt;https://github.com/shamansir/purescript-ffm&lt;/a&gt;. To run it, an least four commands are needed to be executed (the project is working on &lt;code&gt;spago&lt;/code&gt; + &lt;code&gt;parcel&lt;/code&gt; ):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;purescript&lt;/span&gt; &lt;span class="n"&gt;spago&lt;/span&gt;
&lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt;
&lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;
&lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be able now to go to &lt;a href="http://localhost:1234" rel="noopener noreferrer"&gt;http://localhost:1234&lt;/a&gt; and observe some weird interface there, which we cover below, but first let’s explain the basic logic behind it.&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%2Fi%2Fgwmdiwty8lvc6xi4o462.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%2Fi%2Fgwmdiwty8lvc6xi4o462.png" alt="The Interface" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also has tests made with awesome &lt;code&gt;purescript-spec&lt;/code&gt;, you can easily run them using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fi%2Fm0z9b1q35lm48c9c6dx8.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%2Fi%2Fm0z9b1q35lm48c9c6dx8.png" alt="Alt Text" width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is a museum and it has (yet discovered by me to the moment) three stages of development:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Plot
&lt;/h3&gt;

&lt;p&gt;First, you are catching bugs and fishing and deliver these specimens to the bear (bear with me, I can promise we are all sane!), who is very serious about business and who collects your species until the amount reaches five. &lt;/p&gt;

&lt;p&gt;They all should be unique though, and that requirement goes through the whole system. Everything that already exists in the museum or extends the amount of one, will be returned back to you. &lt;/p&gt;

&lt;p&gt;Only after that, you are introduced to Blathers, the owl that lives in a tent and has some botanical and archeological skills. Now, in addition to aggregating bugs and fish, you also can dig up the fossils with the shovel, which are then “unpacked” by Blathers to some specific part of an outdated animal skeleton and returned to you, only after that you know what was inside of that fossil. &lt;/p&gt;

&lt;p&gt;And so now you deliver the bugs and fossils to the tent, and the owl has one &lt;em&gt;side effect&lt;/em&gt; of telling you the very detailed, perfectly scientific, story about every new creature you’ve found. You always have an option to decline and nobody will judge you (&lt;em&gt;won’t they, actually? there are rumours that the animals were not that polite in the previous games of series…&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;Now, when you reach the 15 of species (unique unpacked fossils also count as one), you can select the place for the large fancy museum and have it built it on the next day. It has three floors and all your bugs and fish and skeletons (not the ones from the closet) are located in here. &lt;/p&gt;

&lt;p&gt;And now you also get a nice option to deliver several unique things at once and politely omit the _side effect_of hearing the story. Sometimes it looks like Blathers is actually also bored with telling, but the curiosity, or may be ethic rules, keeps me asking him to tell and tell them again and again.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Interface
&lt;/h3&gt;

&lt;p&gt;In the interface, there are some buttons at the top, and they are only usable by player, which means &lt;em&gt;you&lt;/em&gt;. You are the God here and the button of the God is the one that just produces errors, for sure. Also you can dig, catch bugs and go fishing, but ensure to press these buttons a lot of times, because the chance that you get something in response is 40%. We do use random numbers here! &lt;/p&gt;

&lt;p&gt;Aside from that, you can see all the species you have (none for the moment), grouped by bugs/fish/skeletons/fossils and then by quantity and kind, and much more details about the &lt;em&gt;future&lt;/em&gt; museum. &lt;/p&gt;

&lt;p&gt;You can deliver the items you have to the museum, but the museum will take only the unique ones, and just one item of such (even though you’re God and they should’ve store pairs of them, ignorant… animals!). Everything else gets back to you. &lt;/p&gt;

&lt;p&gt;But the situation with &lt;em&gt;fossils&lt;/em&gt; is different! You don’t know what’s inside of them. You can not deliver them to the museum at the first stage where Tom Nook rules the party, since he is unable to unwrap that fossils too. Only Blathers has required education, so you have to upgrade to the tent before delivering them. Also, after that he only unwraps them and returns them back as the skeleton parts, which you may then try to deliver the usual way.&lt;/p&gt;

&lt;p&gt;Upgrading: When you have delivered enough of unique species to upgrade (5 for the tent, 10 for the building), the museum will close until you will find the location for the tent or the building. In the game, you would have to wait for a day after that, but we are not that realistic here, so when you find the location (by pressing the corresponding button and so choosing it randomly) the museum just opens back again.&lt;/p&gt;

&lt;p&gt;I won’t inspect the source line by line, but rather will just discuss with you the most important parts.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Structure of Code
&lt;/h3&gt;

&lt;p&gt;The most interesting for you should be the &lt;code&gt;Example.purs&lt;/code&gt; file, it has all the logic discussed above. Secondly, the &lt;code&gt;Ui.purs&lt;/code&gt;, which specifies the rendering engine in just a few lines. And the last may be &lt;code&gt;VDom.purs&lt;/code&gt;, which reuses the &lt;code&gt;Halogen&lt;/code&gt;’s &lt;code&gt;VDom&lt;/code&gt; engine to actually render stuff and run the User Interface.&lt;br&gt;
And, of course, &lt;code&gt;Fsm/Fsm.purs&lt;/code&gt;, but we have discussed it in the details through all the first part, so you already know everything about it, don’t bother looking!&lt;/p&gt;
&lt;h3&gt;
  
  
  The FSM
&lt;/h3&gt;

&lt;p&gt;Okay, just a quick look. It is different from the article in the sense that it collects effects in the list rather than produces a singe effect with a list of actions as the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Fsm&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Fsm&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything else is the same and takes just a dozen of lines. Well, ten dozens, but it’s just because we have no economy for lines of code in functional languages, it is the infinite resource here!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Rendering
&lt;/h3&gt;

&lt;p&gt;We just redefine the original &lt;code&gt;Fsm&lt;/code&gt; with model being the &lt;code&gt;Covered&lt;/code&gt;type and use it for the &lt;code&gt;Ui&lt;/code&gt;, that’s it:&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;type&lt;/span&gt; &lt;span class="kt"&gt;CoveredFsm&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;Fsm&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Ui&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Ui&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;CoveredFsm&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;make'&lt;/code&gt; functions, they are different in the way of joining or not joining errors, as discussed in the original article:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;make&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="n"&gt;action&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="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Ui&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Ui&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Fsm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Fsm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;joinWith&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt;


&lt;span class="n"&gt;make'&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Semigroup&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="n"&gt;action&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="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Ui&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
&lt;span class="n"&gt;make'&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Ui&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Fsm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt;
            &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Fsm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;joinWith&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appendErrors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;We have &lt;code&gt;Action&lt;/code&gt; and &lt;code&gt;Model&lt;/code&gt; and &lt;code&gt;Error&lt;/code&gt; here and also he have an &lt;code&gt;App&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; 
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; 
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; 
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Ui&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create it using &lt;code&gt;Ui.make&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;App&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Ui&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make'&lt;/span&gt; &lt;span class="n"&gt;update'&lt;/span&gt; &lt;span class="n"&gt;view'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the quotes. If you change &lt;code&gt;make'&lt;/code&gt; to &lt;code&gt;make&lt;/code&gt;, then it no more requires &lt;code&gt;Semigroup&lt;/code&gt; for errors, so they are aggregated no more, just the latest one is going through all the engine. You’ll notice it when you run the example and do something erroneous or just press the almighty “Produce Error” button. Just a subtle change leads to such serious consequences! &lt;/p&gt;

&lt;p&gt;&lt;code&gt;update'&lt;/code&gt; is different from &lt;code&gt;update&lt;/code&gt; only by the fact it unwraps the &lt;code&gt;Covered&lt;/code&gt; model since in the logic we don’t care, were there errors before or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;update'&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; 
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; 
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;update'&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;covered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recover&lt;/span&gt; &lt;span class="n"&gt;covered&lt;/span&gt;

&lt;span class="n"&gt;update&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; 
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; 
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;view'&lt;/code&gt; with the quote just also renders the error(-s) when it (they) happened before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;view'&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;
&lt;span class="n"&gt;view'&lt;/span&gt; &lt;span class="n"&gt;covered&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;covered&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Carried&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
        &lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;
                &lt;span class="kt"&gt;[ ]&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
                &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="s"&gt;"Latest errors: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
                &lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run it, we use &lt;code&gt;Ui.run&lt;/code&gt; in the &lt;code&gt;VDom.purs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Regarding &lt;code&gt;Semigroup&lt;/code&gt; and &lt;code&gt;Error&lt;/code&gt;s, we have a special constructor for the errors to collect them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; 
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;Semigroup&lt;/code&gt; implementation:&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;instance&lt;/span&gt; &lt;span class="n"&gt;semigroupError&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Semigroup&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;append&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="n"&gt;listA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="n"&gt;listB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;listA&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listB&lt;/span&gt;
    &lt;span class="n"&gt;append&lt;/span&gt; &lt;span class="n"&gt;singleError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;singleError&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;
    &lt;span class="n"&gt;append&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;singleError&lt;/span&gt; 
        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;singleError&lt;/span&gt;
    &lt;span class="n"&gt;append&lt;/span&gt; &lt;span class="n"&gt;singleErrorA&lt;/span&gt; &lt;span class="n"&gt;singleErrorB&lt;/span&gt; 
        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;SeveralErrors&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;singleErrorA&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;singleErrorB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may just use &lt;code&gt;List Error&lt;/code&gt; when you specify the &lt;code&gt;App&lt;/code&gt; and don’t care about &lt;code&gt;Semigroup&lt;/code&gt; instance at all, but I wanted to demonstrate how easy it is to change from the multi-error mode to the single-error mode using one press of a key and here you need a bit more pressing:&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;type&lt;/span&gt; &lt;span class="kt"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Ui&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Actions, Producing
&lt;/h3&gt;

&lt;p&gt;From now we discuss the &lt;code&gt;update&lt;/code&gt; function code, the one without a quote.&lt;/p&gt;

&lt;p&gt;There are no cases in this example where several actions would be produced in response to another action, may be it needs improvement.&lt;/p&gt;

&lt;p&gt;If there would be one, it would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kt"&gt;Dig&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kt"&gt;Catch&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kt"&gt;GoFishing&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now, it is usually just one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pure model /\ pure Deliver : Nil
...
pure model /\ pure DeliverFossils : Nil
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Effects, Producing
&lt;/h3&gt;

&lt;p&gt;In this implementation each effect is bound to an action, for example to decide if you catch something at all and if you do, what kind of bug you’ve got, we use random numbers and random weight distribution, which is surely an effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;playerUpdate&lt;/span&gt; &lt;span class="kt"&gt;Catch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;model&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;n1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;
        &lt;span class="n"&gt;n2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;
        &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt;
             &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;decide&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;GetBug&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;decide'&lt;/span&gt; &lt;span class="n"&gt;bugsChoice&lt;/span&gt; &lt;span class="kt"&gt;Tarantula&lt;/span&gt; &lt;span class="n"&gt;n2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="kt"&gt;GetNoBug&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt; &lt;span class="n"&gt;n1&lt;/span&gt;
        &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the first number &lt;code&gt;n1&lt;/code&gt; we decide by 40% possibility if there is a bug, and then we use the second number &lt;code&gt;n2&lt;/code&gt; to decide which kind of bug exactly, using this weight definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;bugsChoice&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Butterfly&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="mf"&gt;0.40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Spider&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="mf"&gt;0.30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Ladybug&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Caterpillar&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tarantula&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we either return the action &lt;code&gt;GetNoBug&lt;/code&gt; or  the action&lt;code&gt;GetBug &amp;lt;SomeBug&amp;gt;&lt;/code&gt; in response.&lt;/p&gt;

&lt;p&gt;To find a location for the museum, we also use random numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;playerUpdate&lt;/span&gt; &lt;span class="kt"&gt;FindMuseumSpot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Player&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="kt"&gt;LocateMuseumSpot&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="kt"&gt;Location&lt;/span&gt;
           &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;/\&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are eager to play with the code, take the challenge of implementing the effect of telling the scientific story by Blathers, it should be as easy as these examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Errors, Producing
&lt;/h3&gt;

&lt;p&gt;For example, you can’t locate the spot for the museum if it’s open, it only can be closed, so we produce an error if we’ve met that case. Previously I’ve disabled the buttons in the interface if such conditions would happen, but lately I decided that it is better demonstrates the error system if they are always enabled.&lt;/p&gt;

&lt;p&gt;To produce an error (and it can be accumulated automatically!), it is just as easy as &lt;code&gt;cover&lt;/code&gt; the previous model in the &lt;code&gt;Covered&lt;/code&gt; instance together with that error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;playerUpdate&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;LocateMuseumSpot&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;museum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;otherwise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NoLocatingAllowed&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cover&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we have &lt;code&gt;SeveralErrors&lt;/code&gt; there, it is also possible to produce lists of them. Which would be merged automatically with the previous ones thanks to the &lt;code&gt;UI.make'&lt;/code&gt; implementation and &lt;code&gt;Semigroup&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;Some more examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;playerUpdate&lt;/span&gt; &lt;span class="kt"&gt;Deliver&lt;/span&gt; 
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;canDeliver&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;museum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kt"&gt;ConsiderSpecies&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;otherwise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NoSpeciesDeliveryAllowed&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cover&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;

&lt;span class="n"&gt;playerUpdate&lt;/span&gt; &lt;span class="kt"&gt;DeliverFossils&lt;/span&gt; 
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;canDeliverFossils&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;museum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kt"&gt;ConsiderFossils&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;otherwise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NoFossilsDeliveryAllowed&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cover&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Nil&lt;/span&gt;     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Haven’t I wrote in the first part that I don’t use separate constructors for different errors? I lied!&lt;/p&gt;

&lt;h3&gt;
  
  
  Finalé
&lt;/h3&gt;

&lt;p&gt;Now that is really it. I hope this pair of articles will find it useful for somebody. &lt;/p&gt;

&lt;p&gt;Again, please feel free to comment and everything else is appreciated.&lt;/p&gt;

&lt;p&gt;I am &lt;a href="https://twitter.com/shaman_sir" rel="noopener noreferrer"&gt;&lt;code&gt;shaman_sir&lt;/code&gt;&lt;/a&gt; in Twitter and usually I post either functional programming things or the things about generative graphics (sometimes my own), and I can promise that more to come, especially where these both topics meet each other. Stay tuned.&lt;/p&gt;

&lt;p&gt;Also, my personal blog which demonstrates the weird ways I took to reach the PureScript enlightenment, and where I should add these too articles a bit later:&lt;br&gt;
&lt;a href="https://shamansir.github.io/blog/" rel="noopener noreferrer"&gt;https://shamansir.github.io/blog/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you!&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>frp</category>
      <category>functional</category>
    </item>
    <item>
      <title>PureScript: UI driven by Finite State Machines and Event Streams</title>
      <dc:creator>Anton Kiłka</dc:creator>
      <pubDate>Thu, 23 Apr 2020 09:39:04 +0000</pubDate>
      <link>https://dev.to/shamansir/purescript-ui-driven-by-finite-state-machines-and-event-streams-994</link>
      <guid>https://dev.to/shamansir/purescript-ui-driven-by-finite-state-machines-and-event-streams-994</guid>
      <description>&lt;p&gt;I should've call the article &lt;em&gt;”The Elm Architecture in PureScript”&lt;/em&gt;, but both the inner demons and the inner angels said "Oh, dear, no!". Still I can't deny the article covers such topic as well.&lt;/p&gt;

&lt;p&gt;Among that, this article covers the easiest way for accumulating errors and recovering to the last successful state of the application in a flick of the wrist (I love &lt;a href="https://www.youtube.com/watch?v=mrApaXj5QmA" rel="noopener noreferrer"&gt;that song&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Also I plan to abandon explaining why I chose PureScript and get straight to the details. Just keep in mind that Haskell and PureScript are bro-s: each one is pretending to be radically different, but they share truly a lot of common.&lt;/p&gt;

&lt;p&gt;The project I am working on, &lt;em&gt;Noodle&lt;/em&gt;, has quite complex UI and API as well. For some time I struggled in finding the proper architecture to define both of them, because my intuition strictly said there are common patterns I am yet too blind to see. In pure functional languages it is really easy to write some shitty code, just not making it public, and reason about it later, while you have everything working and stable. And not to confuse you with the harsh word &lt;em&gt;shitty&lt;/em&gt;, I have a bunch of unit tests to ensure the logic is what I expect it to be. Also, I think, in leaning to perfection it is important to know where to do a step off the road for some time and get back to this infinite road with new strengths and visions… but enough morals.&lt;/p&gt;

&lt;p&gt;When I discovered the article &lt;a href="https://wickstrom.tech/finite-state-machines/2017/11/10/finite-state-machines-part-1-modeling-with-haskell.html" rel="noopener noreferrer"&gt;Finite State Machines in Haskell&lt;/a&gt; and read it, everything stood on its place. This was the pattern! Not to oblige you reading the article, the key point is that Finite State Machine is as easy as this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;finiteStateMachine&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is our famous &lt;em&gt;”The Elm Architecture”&lt;/em&gt; in its essence, simplified to the origins where it was actually born. &lt;/p&gt;

&lt;p&gt;The function, which receives some &lt;em&gt;action&lt;/em&gt; (say, &lt;code&gt;DecrementCounter&lt;/code&gt; or &lt;code&gt;WithdrawMoney&lt;/code&gt; or &lt;code&gt;JustRobThePlace&lt;/code&gt;), gets &lt;em&gt;previous model&lt;/em&gt; and evaluates to the &lt;em&gt;new modified model&lt;/em&gt;. Some people prefer it flipped, so the model comes as the first argument. Those actions are usually the sum types so it is easy to keep them in one place and have a birds-eye view on the processes happening in your application. &lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Let’s move the practical example &lt;a href="https://dev.to/shamansir/purescript-ui-driven-by-finite-state-machines-and-event-streams-part-ii-the-example-3m77"&gt;to another part of the article&lt;/a&gt; and for now mostly speak theory. Don’t be confused, in the end of this part I’ll give the complete working code for FSM using FRP, since it’s just a few lines of code. First, we will define the signature, then the way to &lt;code&gt;make&lt;/code&gt; it and, finally, &lt;code&gt;run&lt;/code&gt; it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considering Effects
&lt;/h2&gt;

&lt;p&gt;Both the UI and API in my case require some side effects to be performed. For API it’s, for example, generating a random UUID for any new entity. And, since I use FRP events, subscribing to event streams or cancelling them is also a side effect. In case of UI, it is &lt;code&gt;Event.stopPropagation&lt;/code&gt; (where &lt;em&gt;event&lt;/em&gt; is HTML event, not the FRP one), &lt;code&gt;requestAnimationFrame&lt;/code&gt;, drawing on canvas, some connections to JavaScript using FFI. Some of such effects should be &lt;code&gt;Aff&lt;/code&gt; though, since they are asynchronous, but it doesn’t really &lt;em&gt;affect&lt;/em&gt; what we discuss in any matter.&lt;/p&gt;

&lt;p&gt;Separating effects from the pure actions is very important in pure functional languages, still it doesn’t mean you can’t use them, just keep them marked as such and, preferably, sorted (see below).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;finiteStateMachine&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Elm, every &lt;code&gt;update&lt;/code&gt; function returns &lt;code&gt;Cmd&lt;/code&gt; along with the model, which is also the wrapper for the effects, still you may need some effort to realise it. Actually, they separate model from the effects, and that’s smart thing to do, so let’s do the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;finiteStateMachine&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you ever used the &lt;code&gt;Spork&lt;/code&gt; library, you may want to draw attention to the fact that they also use a sum type to describe effects. So in my case they would have &lt;code&gt;NewUUID&lt;/code&gt; and &lt;code&gt;StopPropagation&lt;/code&gt; constructors for the &lt;code&gt;effect&lt;/code&gt; type instances and functions like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;finiteStateMachine&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;

&lt;span class="n"&gt;performEffect&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;performEffect&lt;/code&gt; is performed after every call to FSM.  That’s a really good way to sort the effects and don’t put them into one basket. But I decided not to do that in the end: I had such code before and may be I’ll get it back in some form, but during the rewriting stage I wanted not to bother thinking about that, and now I have the working code, which is open to return to this approach, at some point, maybe. Just please notice that it’s really something to think through.&lt;/p&gt;

&lt;p&gt;Actually the Elm’s &lt;code&gt;Cmd&lt;/code&gt; is doing the similar thing by requiring you to provide functions which return specific actions, but more on that later, just in the next chapter. &lt;/p&gt;

&lt;p&gt;If you have considered that, let’s get back to the latest specification and stick with it in the end of this section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;finiteStateMachine&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The article on Haskell’s way covers it really well with the examples using &lt;code&gt;IO&lt;/code&gt;, which is the same concept as &lt;code&gt;Effect&lt;/code&gt; in PureScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursing to Actions
&lt;/h2&gt;

&lt;p&gt;If you are willing to keep actions minimalistic, meaning that each action is modifying the model in one single and predictable way, defined by the name of such action (e.g. not just &lt;code&gt;RobTheBank&lt;/code&gt;, but rather splitting it into &lt;code&gt;BuyToyShotgun&lt;/code&gt;, &lt;code&gt;DefineWorkingHours&lt;/code&gt;, &lt;code&gt;FindOutSecuritySchedule&lt;/code&gt;, &lt;code&gt;WearMask&lt;/code&gt;, &lt;code&gt;EnterTheBank&lt;/code&gt;, &lt;code&gt;GetToCachier&lt;/code&gt;, &lt;code&gt;TryNotToPee&lt;/code&gt; and so on, it’s not me to give you details on how to do it, just visit &lt;code&gt;wikihow.com&lt;/code&gt; on robbing banks), you would see that one action sometimes requires other actions to be performed. Without wearing a mask, it’s better not to start the robbing procedure at all (depends on your case, for sure). &lt;/p&gt;

&lt;p&gt;So it becomes handy to return the list of the actions to perform next, which can be empty, of course.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;finiteStateMachine&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are still thinking about Elm, you may recall that &lt;code&gt;Cmd.batch&lt;/code&gt; thing, which represents effects that are evaluated from &lt;code&gt;update&lt;/code&gt; function where every effect is bound to the specific action. Let’s also join this concept with the specification of effects we did previously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;finiteStateMachine&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It could be another way around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;finiteStateMachine&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way you can not share data between the effects you perform, only with carrying them together with actions. Which is really a good thing for making things really pure and minimalistic. But I decided to avoid that for the sake of simplicity, still you are always free to choose the proper way by just replacing one with another and make it compile.&lt;/p&gt;

&lt;p&gt;I also made some helpers to refrain from typing &lt;code&gt;pure&lt;/code&gt; in the end of &lt;code&gt;do&lt;/code&gt;-blocks a lot. If you use &lt;code&gt;List (Effect action)&lt;/code&gt; technique, you don’t need them, obviously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;doNothing&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;doNothing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kt"&gt;[]&lt;/span&gt;

&lt;span class="n"&gt;single&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;single&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt;

&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we are ready to define our data type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s also define the function to create such instances, which is just a type constructor for now, but we leave the opportunity for it to be changed later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;make&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s actually it! We can represent all other things just with reusing this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errors, Introducing &lt;code&gt;Covered&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I have to confess that I am using my own data type to work with errors. As much of you probably did, I researched the problem of accumulating errors (no, I do swear I have no intention &lt;a href="https://www.parsonsmatt.org/2018/11/03/trouble_with_typed_errors.html" rel="noopener noreferrer"&gt;to have separate types for them&lt;/a&gt;!) and no solution satisfied me, except this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Carried&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;Carried&lt;/code&gt; means we &lt;em&gt;carry&lt;/em&gt; the value and it’s all good. And &lt;code&gt;Recovered&lt;/code&gt; means we had some error and the value was &lt;em&gt;recovered&lt;/em&gt; from that failure.  It just always stores the last successful value, along with the error, when it had un-fortune to happen. The single and the latest error, same as for value,.. unless you have &lt;code&gt;Semigroup e =&amp;gt; Covered e a&lt;/code&gt;! &lt;/p&gt;

&lt;p&gt;Imagine you are cooking something and if you have forgot to buy some ingredient, you just skip it and happily continue the process, but notice such failure in the list of failures to avoid in the future. Or you broke the eggs together with the eggshells while preparing the cake, so you just suck the eggs and the eggshells back from the stock, and it’s all fine, you just put a notice near the cake that eggshells were there, and the eggs were also required to be reverted due to error, but it’s all clean now, &lt;em&gt;bon appétit&lt;/em&gt;. Seems I am not that good in examples.&lt;/p&gt;

&lt;p&gt;So the FSM, where it is possible to keep the last error (or accumulate errors), looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But since we need to alter the &lt;code&gt;update&lt;/code&gt; function behaviour, and it should be imprinted in the logic of such machine, it could be better to make it a data type (and ensure to hide the constructor):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;Either&lt;/code&gt; is the purest way of dealing with errors, I use it as an atomic part of the API: every function that belongs to the core API and can fail with some error, evaluates to &lt;code&gt;Either&lt;/code&gt; and nothing else. So does the &lt;code&gt;update&lt;/code&gt; function that wraps the API, except that &lt;em&gt;inbetween&lt;/em&gt; the calls, after the action was applied to the model, it either (no pun intended) replaces &lt;code&gt;Either&lt;/code&gt; with the &lt;code&gt;Covered&lt;/code&gt;, holding the previous model (which we always have in &lt;code&gt;update&lt;/code&gt; function) &lt;em&gt;or&lt;/em&gt;, if the error type satisfies &lt;code&gt;Semigroup&lt;/code&gt; typeclass, it glues the errors from the previous call with the ones from the ongoing call. &lt;/p&gt;

&lt;p&gt;But first, let’s review the approach where we just store the last error and rollback to a last successful state. For that you’ll need a function that moves the error from one &lt;code&gt;Covered&lt;/code&gt; instance to another, if there is one. The function is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;consider&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;consider&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="n"&gt;errA&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Carried&lt;/span&gt; &lt;span class="n"&gt;vB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="n"&gt;errA&lt;/span&gt; &lt;span class="n"&gt;vB&lt;/span&gt;
&lt;span class="n"&gt;consider&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="n"&gt;coveredB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coveredB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It seems to satisfy &lt;code&gt;Alt&lt;/code&gt; laws (but not &lt;code&gt;Alternative&lt;/code&gt;), so we may assign the &lt;code&gt;&amp;lt;|&amp;gt;&lt;/code&gt; operator for it. And this way you can use this function for folding the event streams of &lt;code&gt;Covered&lt;/code&gt; values, for example.&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;instance&lt;/span&gt; &lt;span class="n"&gt;coveredAlt&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Alt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;alt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;consider&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And so we need to define custom &lt;code&gt;make&lt;/code&gt; function for &lt;code&gt;CoveredFSM&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;make&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   
    &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt;
        &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;model'&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;effects'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
            &lt;span class="kr"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;effects'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If storing the last error satisfies your needs, you could stop at this point. &lt;/p&gt;

&lt;p&gt;If you want to store all the errors happened, you’ll need some function to append errors from one &lt;code&gt;Covered&lt;/code&gt; instance to another. Let’s call it &lt;code&gt;appendErrors&lt;/code&gt;—it’s not &lt;code&gt;Semigroup&lt;/code&gt;’s &lt;code&gt;append&lt;/code&gt;, since it operates on errors rather than values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;appendErrors&lt;/span&gt; 
      &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Semigroup&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; 
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;appendErrors&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="n"&gt;errorsA&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="n"&gt;errorsB&lt;/span&gt; &lt;span class="n"&gt;valB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errorsA&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;errorsB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;valB&lt;/span&gt;
&lt;span class="n"&gt;appendErrors&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="n"&gt;errorsA&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Carried&lt;/span&gt; &lt;span class="n"&gt;valB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;Recovered&lt;/span&gt; &lt;span class="n"&gt;errorsA&lt;/span&gt; &lt;span class="n"&gt;valB&lt;/span&gt;
&lt;span class="n"&gt;appendErrors&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Carried&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;coveredB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="n"&gt;coveredB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it’s update function looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;make'&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Semigroup&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; 
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
&lt;span class="n"&gt;make'&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   
    &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt;
        &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;model'&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;effects'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
            &lt;span class="kr"&gt;in&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;appendErrors&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="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;effects'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A trained eye may notice a pattern here: we just have one function that changes the way how we join the previous model with the next one. If it sounds like &lt;em&gt;folding&lt;/em&gt; to you, I share your inference. By defining a data type or &lt;code&gt;newtype&lt;/code&gt; we are ensuring that user uses the proper instance of &lt;code&gt;CoveredFSM&lt;/code&gt; and don’t forget to specify the way to glue errors. But that doesn’t prevent us from adding a helper to &lt;code&gt;FSM&lt;/code&gt;, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;joinWith&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
&lt;span class="n"&gt;joinWith&lt;/span&gt; &lt;span class="n"&gt;joinF&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;model'&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;effects'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
            &lt;span class="kr"&gt;in&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;joinF&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="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;effects'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now our &lt;code&gt;make&lt;/code&gt; functions become much fancier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;make&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;joinWith&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt;

&lt;span class="n"&gt;make'&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Semigroup&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; 
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
&lt;span class="n"&gt;make'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   
    &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;joinWith&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appendErrors&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the downsides of using &lt;code&gt;Covered&lt;/code&gt; could be that it’s not that fancy to use&lt;code&gt;Covered&lt;/code&gt; in &lt;code&gt;do&lt;/code&gt;-notation, rather than its brothers &lt;code&gt;Maybe&lt;/code&gt; and &lt;code&gt;Either&lt;/code&gt; since (unless you wrap the &lt;code&gt;Either&lt;/code&gt;-producing function in &lt;code&gt;Covered&lt;/code&gt; later, as noted above) you always have to specify the fallback value and it is usually the same value through all the block. I suppose it could potentially be solved with monad transformers and &lt;code&gt;State&lt;/code&gt; monad, and if yes, please tell in the comments how.&lt;/p&gt;

&lt;h2&gt;
  
  
  FRP and Running
&lt;/h2&gt;

&lt;p&gt;Finally, let’s implement it! Using event streams from the &lt;a href="https://github.com/paf31/purescript-event" rel="noopener noreferrer"&gt;FRP Events Library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s rather simple: we provide the initial model (&lt;code&gt;init&lt;/code&gt;), we create the actions stream, and on every push of some action, we call the FSM’s &lt;code&gt;update&lt;/code&gt; function on it, skipping the effects from previous update. And we subscribe to the stream of updates to perform all the effects requested after the update.  Then we provide user with the ability to &lt;code&gt;push&lt;/code&gt; actions into system.  Which is quite useful for UIs for example, to push some specific action in response to the HTML event handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;run&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
            &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;
    &lt;span class="kr"&gt;let&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fst&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;actions&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kt"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt;
        &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;eff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;eff&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;traverse_&lt;/span&gt; &lt;span class="n"&gt;pushAction&lt;/span&gt;
    &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This has a little sense though, since you have no way to see what models are, so let’s add the ability to specify the subscription to models. The problem with just returning the event stream of models is that if you subscribe to it after the subscription which performs the effects, you get the results of these calls in the model stream as well, which you would probably like to avoid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;run&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
            &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subModels&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pushAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;
    &lt;span class="kr"&gt;let&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fst&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;actions&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kt"&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;models&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fst&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt;
    &lt;span class="n"&gt;stopModelSubscription&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="n"&gt;subModels&lt;/span&gt;
    &lt;span class="n"&gt;stopPerformingEffects&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt;
        &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;eff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;eff&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;traverse_&lt;/span&gt; &lt;span class="n"&gt;pushAction&lt;/span&gt;
    &lt;span class="n"&gt;pure&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pushAction&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stopModelSubscription&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stopPerformingEffects&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 use it to &lt;em&gt;fold&lt;/em&gt; some list of actions and get the latest model out of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;fold&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Foldable&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="n"&gt;fsm&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="n"&gt;actionList&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;lastValRef&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;pushAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; 
        &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;fsm&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flip&lt;/span&gt; &lt;span class="kt"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="n"&gt;lastValRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;
    &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;traverse_&lt;/span&gt; &lt;span class="n"&gt;pushAction&lt;/span&gt; &lt;span class="n"&gt;actionList&lt;/span&gt;
    &lt;span class="n"&gt;lastVal&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="n"&gt;lastValRef&lt;/span&gt;
    &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;lastVal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running a &lt;code&gt;CoveredFSM&lt;/code&gt; instance is just calling the &lt;code&gt;FSM.run&lt;/code&gt; for the underlying instance, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;run&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
            &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;CoveredFSM&lt;/span&gt; &lt;span class="n"&gt;fsm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;fsm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  UI, Renderers and VDOM
&lt;/h2&gt;

&lt;p&gt;Now, to the UI part. Finite State Machine only lacks one addition to be able to render model into some view. And this addition is easily represented with a corresponding function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The UI which stores the information about errors is:&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;type&lt;/span&gt; &lt;span class="kt"&gt;CoveredUI&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&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;view&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we hide the &lt;code&gt;FSM&lt;/code&gt; under the &lt;code&gt;UI&lt;/code&gt; type constructor, we may avoid using &lt;code&gt;CoveredFSM&lt;/code&gt; type and provide making functions like these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;make&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt; 


&lt;span class="n"&gt;makeCovered&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&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="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
&lt;span class="n"&gt;makeCovered&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;joinWith&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt;


&lt;span class="n"&gt;makeCovered'&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Semigroup&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; 
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;action&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="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
&lt;span class="n"&gt;makeCovered'&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; 
            &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;joinWith&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appendErrors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, this way running UI is as easy as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;run&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Canceler&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;fsm&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pushView&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; 
        &lt;span class="kt"&gt;FSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;fsm&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pushView&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;viewF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;carry&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;pure&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What user gets is response is the stream of views and we can now feed it to the rendering engine. &lt;/p&gt;

&lt;p&gt;Let’s address to &lt;code&gt;Halogen&lt;/code&gt; VDOM engine which is distributed in a &lt;a href="https://github.com/purescript-halogen/purescript-halogen-vdom" rel="noopener noreferrer"&gt;separate package&lt;/a&gt;. First, we now definitely render to HTML:&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;type&lt;/span&gt; &lt;span class="kt"&gt;HtmlRenderer&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;CoveredUI&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another confession I have to make: currently, yes, it’s the &lt;code&gt;Html&lt;/code&gt; from the &lt;code&gt;Spork&lt;/code&gt; library. But since in this article we intentionally decline the techniques behind the libraries like &lt;code&gt;Spork&lt;/code&gt; for the sake of learning, I had to keep it in secret till the end. Also, it is still up to you which output you want to have, &lt;em&gt;SVG&lt;/em&gt; or &lt;em&gt;canvas&lt;/em&gt; or &lt;em&gt;text string&lt;/em&gt; or may be even you will decide to output to terminal using &lt;em&gt;ASCII&lt;/em&gt;, for all &lt;code&gt;view&lt;/code&gt;s it works the same!&lt;/p&gt;

&lt;p&gt;And we’re just giving the specific examples.&lt;/p&gt;

&lt;p&gt;This code is a bit more complicated since &lt;code&gt;VDOM&lt;/code&gt; and &lt;code&gt;HTML&lt;/code&gt; API are both not as friendly as ours, but still it works like a charm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;embed&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;HtmlRenderer&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="c1"&gt;-- renderer&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="c1"&gt;-- initial model&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;span class="n"&gt;embed&lt;/span&gt; &lt;span class="n"&gt;sel&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;firstModel&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;doc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;DOM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="kt"&gt;DOM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;
    &lt;span class="n"&gt;mbEl&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;DOM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;querySelector&lt;/span&gt; 
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wrap&lt;/span&gt; &lt;span class="n"&gt;sel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;HTMLDocument&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toParentNode&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;mbEl&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;throwException&lt;/span&gt; 
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="s"&gt;"Element does not exist: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
                &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;UI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;renderer&lt;/span&gt; &lt;span class="n"&gt;firstModel&lt;/span&gt;
            &lt;span class="kr"&gt;let&lt;/span&gt;
                &lt;span class="n"&gt;vdomSpec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;V&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;VDomSpec&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;HTMLDocument&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toDocument&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;
                    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buildWidget&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;buildThunk&lt;/span&gt; &lt;span class="n"&gt;unwrap&lt;/span&gt;
                    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buildAttributes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;P&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buildProp&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;first_vdom&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;EFn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;runEffectFn1&lt;/span&gt;
                            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;V&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buildVDom&lt;/span&gt; &lt;span class="n"&gt;vdomSpec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt; 
                                &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;UI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;renderer&lt;/span&gt; 
                                &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="n"&gt;firstModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;vdom_ref&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;first_vdom&lt;/span&gt;
            &lt;span class="n"&gt;void&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;DOM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appendChild&lt;/span&gt; 
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Machine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extract&lt;/span&gt; &lt;span class="n"&gt;first_vdom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;DOMElement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toNode&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;
                &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;next_view&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
                    &lt;span class="n"&gt;prev_vdom&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="n"&gt;vdom_ref&lt;/span&gt;
                    &lt;span class="n"&gt;next_vdom&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;EFn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;runEffectFn2&lt;/span&gt; 
                                    &lt;span class="kt"&gt;Machine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt; 
                                    &lt;span class="n"&gt;prev_vdom&lt;/span&gt; 
                                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt; &lt;span class="n"&gt;next_view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="n"&gt;next_vdom&lt;/span&gt; &lt;span class="n"&gt;vdom_ref&lt;/span&gt;
                    &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;
            &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait… It turns out the &lt;code&gt;VDOM&lt;/code&gt; engine uses the Finite State Machines under the hood as well. Just &lt;em&gt;a bit&lt;/em&gt; more complicated ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stub and the Actual App
&lt;/h2&gt;

&lt;p&gt;We need some actual code to work with the system, let’s do some stubs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;


&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;


&lt;span class="n"&gt;update&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; 
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; 
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;covered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;covered&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Nil&lt;/span&gt;


&lt;span class="n"&gt;view&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; 
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="kt"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="n"&gt;myRenderer&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;HtmlRenderer&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;myRenderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Ui&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;makeCovered&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, your main function can now be as easy as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&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;VDom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embed&lt;/span&gt; &lt;span class="s"&gt;"#app"&lt;/span&gt; &lt;span class="n"&gt;myRenderer&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it, folks!&lt;/p&gt;

&lt;h2&gt;
  
  
  Aftermath
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Aftermath One
&lt;/h3&gt;

&lt;p&gt;What we defined as &lt;code&gt;UI&lt;/code&gt; is actually containing both application logic (the &lt;code&gt;FSM&lt;/code&gt; stored inside) and rendering (&lt;code&gt;model -&amp;gt; view&lt;/code&gt; function), so you could want to separate these functions or just rename &lt;code&gt;UI&lt;/code&gt; to &lt;code&gt;App&lt;/code&gt; and abstract your application by &lt;code&gt;view&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;App&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;App&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;App'&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;App'&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;MyApp&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;App'&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;


&lt;span class="n"&gt;myApp&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;App&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;myApp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ui&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;makeCovered&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is the same things as &lt;code&gt;HtmlRenderer&lt;/code&gt; defined above, so embedding is no different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&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;VDom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embed&lt;/span&gt; &lt;span class="s"&gt;"#app"&lt;/span&gt; &lt;span class="n"&gt;myApp&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But now you may reuse the same logic for different views.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aftermath Two
&lt;/h3&gt;

&lt;p&gt;Another thing. This would be useful to &lt;code&gt;map&lt;/code&gt; over the &lt;code&gt;FSM&lt;/code&gt; types to convert, for example, &lt;code&gt;FSM action (Either error model)&lt;/code&gt; to &lt;code&gt;FSM action (Covered error model)&lt;/code&gt; with just one call, but if you try to implement &lt;code&gt;Functor&lt;/code&gt; instance for it, you’ll find that to do it we also need a function to convert &lt;code&gt;Covered&lt;/code&gt; to &lt;code&gt;Either&lt;/code&gt; back, which breaks the &lt;code&gt;Functor&lt;/code&gt; logic, of course. But it looks like there’s &lt;code&gt;Invariant&lt;/code&gt;for that!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;imapModel&lt;/span&gt;
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;modelA&lt;/span&gt; &lt;span class="n"&gt;modelB&lt;/span&gt;
     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelA&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;modelB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelB&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;modelA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;modelA&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;modelB&lt;/span&gt;
&lt;span class="n"&gt;imapModel&lt;/span&gt; &lt;span class="n"&gt;mapAToB&lt;/span&gt; &lt;span class="n"&gt;mapBToA&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Fsm&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;modelB&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="kt"&gt;Bifunctor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bimap&lt;/span&gt; &lt;span class="n"&gt;mapAToB&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt; 
            &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;updateF&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; 
            &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;mapBToA&lt;/span&gt; &lt;span class="n"&gt;modelB&lt;/span&gt;


&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;invariantFSM&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Invariant&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FSM&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;imap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;imapModel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…Unfortunately, no, &lt;code&gt;imap&lt;/code&gt; is not enough, because you can not create &lt;code&gt;Covered&lt;/code&gt; out of thin air if there’s &lt;code&gt;Left error&lt;/code&gt; value in &lt;code&gt;Either&lt;/code&gt; part—you need some value to put in &lt;code&gt;Covered&lt;/code&gt;. You may use &lt;code&gt;imap&lt;/code&gt; for any cases where models are easily converted both one to another and back without the loss of data. &lt;/p&gt;

&lt;h3&gt;
  
  
  Aftermath Three
&lt;/h3&gt;

&lt;p&gt;Remember I noticed that it’s better to use &lt;code&gt;List (Effect action)&lt;/code&gt; rather than &lt;code&gt;Effect (List action)&lt;/code&gt;? It indeed is, and it requires just one change in the code of the &lt;code&gt;run&lt;/code&gt; function. To replace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;    &lt;span class="n"&gt;stopPerformingEffects&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt;
        &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;eff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;eff&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;traverse_&lt;/span&gt; &lt;span class="n"&gt;pushAction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;    &lt;span class="n"&gt;stopPerformingEffects&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt;
        &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="n"&gt;effs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;traverse_&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;pushAction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;effs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done. The example is written using &lt;code&gt;List (Effect Action)&lt;/code&gt;, by the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aftermath Four
&lt;/h3&gt;

&lt;p&gt;And the last. &lt;code&gt;Covered&lt;/code&gt; type has the &lt;code&gt;Bind&lt;/code&gt; instance such as (where &lt;code&gt;recover&lt;/code&gt; extracts the value from the &lt;code&gt;Covered&lt;/code&gt; type):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;coveredBind&lt;/span&gt; 
    &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Semigroup&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bind&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Covered&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="n"&gt;covered&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appendErrors&lt;/span&gt; &lt;span class="n"&gt;covered&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;recover&lt;/span&gt; &lt;span class="n"&gt;covered&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ve seen &lt;code&gt;appendErrors&lt;/code&gt; above. So now you know, that you may use &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt; anywhere to join errors between two &lt;code&gt;Covered&lt;/code&gt; values in any place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aftermath Five
&lt;/h3&gt;

&lt;p&gt;One project that inspired me for using PureScript with FRP is &lt;a href="https://david-peter.de/articles/flare/" rel="noopener noreferrer"&gt;Flare&lt;/a&gt;. The way it uses Functor and Applicative instances to adapt the values inside of the components is just awesome and they are all just one-liners. So the future plan is to find a way to do similar things with FSMs.&lt;/p&gt;

&lt;h3&gt;
  
  
  And Everything Else…
&lt;/h3&gt;

&lt;p&gt;Don’t forget to take a look at &lt;a href="https://dev.to/shamansir/purescript-ui-driven-by-finite-state-machines-and-event-streams-part-ii-the-example-3m77"&gt;the example&lt;/a&gt; which has the code with the effects, and passing actions from the &lt;code&gt;UI&lt;/code&gt; and everything you would question about during reading this article. Hope you enjoyed it.  &lt;/p&gt;

&lt;p&gt;Also, here is the &lt;a href="https://github.com/shamansir/purescript-fsm" rel="noopener noreferrer"&gt;example source code&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;On the other hand, the article could contain errors and misleading information, not intentionally, of course. If you notice such case, please inform the author and the readers as soon as possible by leaving a friendly, yet correcting, comment.&lt;/p&gt;

&lt;p&gt;If you see the ways to improve the approach, please also do comment. Even comment if you have ideas on how to do things worse. &lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;There is some controversy on the effectiveness of the approach, but let’s decide the author (for sure) and the reader (hope so) still think the approach is just awesome, if you use it right. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>purescript</category>
      <category>frp</category>
      <category>functional</category>
    </item>
    <item>
      <title>Hi, I'm Anton Kotenko a.k.a. Ulric Wilfred.</title>
      <dc:creator>Anton Kiłka</dc:creator>
      <pubDate>Thu, 13 Jul 2017 11:17:15 +0000</pubDate>
      <link>https://dev.to/shamansir/hi-im-anton-kotenko-aka-ulric-wilfred</link>
      <guid>https://dev.to/shamansir/hi-im-anton-kotenko-aka-ulric-wilfred</guid>
      <description>&lt;p&gt;I have been coding for 10+ years.&lt;/p&gt;

&lt;p&gt;My blog in &lt;em&gt;English language&lt;/em&gt; &lt;a href="http://shamansir.github.io/blog" rel="noopener noreferrer"&gt;is located here&lt;/a&gt;.&lt;br&gt;
My blog in &lt;em&gt;Russian language&lt;/em&gt; &lt;a href="http://shamansir.github.io/blog/ru" rel="noopener noreferrer"&gt;is located here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Both were abandoned for several years, but I am slowly returning to the roots.&lt;/p&gt;

&lt;p&gt;You can find me on Twitter as &lt;a href="https://twitter.com/shaman_sir" rel="noopener noreferrer"&gt;@shaman_sir&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For almost five years I live in Munich. It was two years in Odessa before that. And from the start I was born in Saint-Petersburg :).&lt;/p&gt;

&lt;p&gt;I work for JetBrains GmbH.&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: JavaScript, Java, whichever.&lt;/p&gt;

&lt;p&gt;I am currently learning more about Elm, Racket, React and Functional Programming in general. I am also quite fascinated with Computer Graphics, User Interfaces, Typography and &lt;a href="https://soundcloud.com/shamansir" rel="noopener noreferrer"&gt;writing Electronic Music&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I gave several talks throughout these years, the slides for some of them &lt;a href="https://speakerdeck.com/shamansir" rel="noopener noreferrer"&gt;are here&lt;/a&gt; and the videos are ... in a lot of places — I'll collect them in one place at some point.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
