<?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: Éber Freitas Dias</title>
    <description>The latest articles on DEV Community by Éber Freitas Dias (@eberfreitas).</description>
    <link>https://dev.to/eberfreitas</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%2F90360%2F3953c330-661d-4fbd-bb4f-ebdb9c7a42d8.png</url>
      <title>DEV Community: Éber Freitas Dias</title>
      <link>https://dev.to/eberfreitas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eberfreitas"/>
    <language>en</language>
    <item>
      <title>Announcing elm-express</title>
      <dc:creator>Éber Freitas Dias</dc:creator>
      <pubDate>Tue, 18 Apr 2023 17:54:46 +0000</pubDate>
      <link>https://dev.to/eberfreitas/announcing-elm-express-4hjn</link>
      <guid>https://dev.to/eberfreitas/announcing-elm-express-4hjn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Not knowing it was impossible, he went there and discovered it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Elm in the backend has always been an idea in the background. Many people have experimented with the concept with varying degrees of success, but it never really took off. In my case, I &lt;a href="https://dev.to/eberfreitas/elm-in-the-server-or-anywhere-else-with-promises-5eoj"&gt;wrote about it&lt;/a&gt;, suggesting that Elm might not be the best language for the backend. Nevertheless, I have just released &lt;a href="https://github.com/eberfreitas/elm-express"&gt;&lt;strong&gt;elm-express&lt;/strong&gt;&lt;/a&gt;, an Elm library with a JavaScript bridge that allows the creation of (almost) pure Elm backends using Express.&lt;/p&gt;

&lt;p&gt;Working with dynamically typed languages like Ruby and Elixir made me want something like Elm in the backend. Although I could have learned Haskell or even tried Rust, I already knew Elm, and it is such a comfortable language to work with that I was willing to take a shot at it in the backend.&lt;/p&gt;

&lt;p&gt;However, the timing may be a little off. In some ways, it feels like the "Express" way of developing for the backend is dying. We are seeing tools that blur the line between backend and frontend, trying to unify how we develop web applications. Tools like &lt;a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html"&gt;Phoenix LiveView&lt;/a&gt;, &lt;a href="https://docs.stimulusreflex.com/"&gt;StimulusReflex&lt;/a&gt;, &lt;a href="https://laravel-livewire.com/"&gt;Laravel Livewire&lt;/a&gt;, &lt;a href="https://remix.run/"&gt;Remix&lt;/a&gt;, &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;, and many others are being developed.&lt;/p&gt;

&lt;p&gt;Moreover, in the Elm world, we have amazing tools like &lt;a href="https://www.lamdera.com/"&gt;Lamdera&lt;/a&gt; and the upcoming &lt;a href="https://elm-pages.com/"&gt;elm-pages v3&lt;/a&gt; which bring the full-stack development experience to Elm.&lt;/p&gt;

&lt;p&gt;Additionally, there is a lot of movement around the Elm language regarding other new and interesting languages like &lt;a href="https://www.roc-lang.org/"&gt;Roc&lt;/a&gt;, &lt;a href="https://gren-lang.org/"&gt;Gren&lt;/a&gt; and even &lt;a href="https://gotoaarhus.com/2023/sessions/2529/elm-on-the-backend"&gt;Elm itself&lt;/a&gt; which will probably reveal new and interesting ways of developing for the backend with the ergonomics of Elm that we like and love.&lt;/p&gt;

&lt;p&gt;So, why do we need elm-express when there are so many interesting tools out there? For me, personally, there are some reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wanted an Elm-like experience for developing backends, and maybe nothing beats Elm itself right now.&lt;/li&gt;
&lt;li&gt;I didn't want to wait for the next great way of developing for the backend with the next Elm-like language.&lt;/li&gt;
&lt;li&gt;I wanted to use something simple with pure Elm, without extra steps or tools like custom compilers.&lt;/li&gt;
&lt;li&gt;I didn't want to feel constrained on the types of apps I can build with the tools at hand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While Elm in the backend may seem appealing, it may not be a wise choice due to the substantial amount of decoding/encoding that could be required and the need for "hacks" like &lt;a href="https://github.com/lobanov/elm-taskport"&gt;taskport&lt;/a&gt; to improve FFI ergonomics.&lt;/p&gt;

&lt;p&gt;Tools like LiveView and Lamdera are really good at removing a lot of the boilerplate and glue code you have to write to get a full-stack experience, which is valuable. My attempt with elm-express will likely result in more boilerplate and glue code. Is that a bad thing? Not necessarily. Being in control of boilerplate and glue code opens up the opportunity to explore more domains, but there is an obvious downside when you are writing lots of code for things that should "just work."&lt;/p&gt;

&lt;p&gt;In the end, elm-express is an experiment. Will it be useful? Maybe. My intention is to write some toy projects with it and see. Maybe it will be a complete disaster, or maybe it will be a really pleasant experience. Perhaps I will come back to talk more about it once I have done something else with it.&lt;/p&gt;

&lt;p&gt;If you use it, let me know. I would love to learn more about other experiments in the area. Thanks for reading.&lt;/p&gt;

</description>
      <category>elm</category>
      <category>express</category>
      <category>backend</category>
    </item>
    <item>
      <title>About lazyness, automation, types and functional languages</title>
      <dc:creator>Éber Freitas Dias</dc:creator>
      <pubDate>Sun, 08 Aug 2021 06:03:38 +0000</pubDate>
      <link>https://dev.to/eberfreitas/about-lazyness-automation-types-and-functional-languages-2gmh</link>
      <guid>https://dev.to/eberfreitas/about-lazyness-automation-types-and-functional-languages-2gmh</guid>
      <description>&lt;p&gt;There is that famous quote attributed to Bill Gates that says: &lt;strong&gt;"I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think it is a stretch, but it makes sense, I guess. The term &lt;em&gt;lazy&lt;/em&gt; is a little too much and could be replaced by "person that optimizes its time".&lt;/p&gt;

&lt;p&gt;I'm not saying on the workaholic sense or productivity freak. I'm talking about the person that wants to use their time most efficiently at times. Avoiding repetitive tasks and trying not to worry about things that can be taken care of in an easier way.&lt;/p&gt;

&lt;p&gt;Automating a task, making it easier to execute, delegating worries, all this looks like a way to value and enrich time.&lt;/p&gt;

&lt;p&gt;Elm, for instance, is a very restrict programming language. It is strongly typed, immutable, and has controlled side effects. What it demands when you develop inside these constraints, pays off by guaranteeing the correctness of your software and the tranquility of not having runtime errors.&lt;/p&gt;

&lt;p&gt;When I use Elm it may look like it is hard to follow its rules and limitations, but I'm choosing the path of least resistance there. After all the computer can aid me to write better software without overloading my brain. If it can perform this kind of task (by using static analysis for instance) I don't have to waste my time and mental bandwidth with it.&lt;/p&gt;

&lt;p&gt;Elm is one example but there are other languages out there like Haskell, Rust, PureScript, and many more.&lt;/p&gt;

&lt;p&gt;When choosing a tool you can value its popularity, expressiveness, who is funding it, etc. But for me, I will always choose to value my time when I can.&lt;/p&gt;

</description>
      <category>opinion</category>
      <category>functional</category>
      <category>types</category>
      <category>elm</category>
    </item>
    <item>
      <title>Pelmodoro - a Pomodoro app built with Elm</title>
      <dc:creator>Éber Freitas Dias</dc:creator>
      <pubDate>Sun, 25 Jul 2021 21:54:23 +0000</pubDate>
      <link>https://dev.to/eberfreitas/pelmodoro-a-pomodoro-app-built-with-elm-5d1l</link>
      <guid>https://dev.to/eberfreitas/pelmodoro-a-pomodoro-app-built-with-elm-5d1l</guid>
      <description>&lt;p&gt;&lt;a href="https://www.pelmodoro.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Pelmodoro&lt;/strong&gt;&lt;/a&gt; is an app that helps you use the &lt;em&gt;pomodoro technique&lt;/em&gt; in your daily life. If you don't know about it take a look at the &lt;a href="https://en.wikipedia.org/wiki/Pomodoro_Technique" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt; article.&lt;/p&gt;

&lt;p&gt;There are many Pomodoro apps out there of different sizes and colors. After using some of them I tried to build my own. &lt;strong&gt;Pelmodoro&lt;/strong&gt; is the result of that effort.&lt;/p&gt;

&lt;p&gt;The app has the traditional timer and a few other features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personalize the number of rounds and sessions duration (work, break, and long break);&lt;/li&gt;
&lt;li&gt;Control how the timer will behave after each session ends;&lt;/li&gt;
&lt;li&gt;Control how you will be notified about session endings;&lt;/li&gt;
&lt;li&gt;Themes!!! 🎨&lt;/li&gt;
&lt;li&gt;Spotify integration to play any playlist during your work rounds;&lt;/li&gt;
&lt;li&gt;Rate your work sessions;&lt;/li&gt;
&lt;li&gt;App usage stats, including worked minutes, breaks, and more;&lt;/li&gt;
&lt;li&gt;Import/export your stats data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of that, &lt;strong&gt;Pelmodoro&lt;/strong&gt; is an &lt;a href="http://offlinefirst.org/" rel="noopener noreferrer"&gt;off-line first&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Progressive_web_application" rel="noopener noreferrer"&gt;PWA&lt;/a&gt;, so you can install it on your mobile device or desktop. I have been using it as a stand-alone app with Edge's PWA support.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7dbjjvqeumg1n29eqhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7dbjjvqeumg1n29eqhf.png" alt="Pelmodoro with themes"&gt;&lt;/a&gt; &lt;br&gt;
&lt;em&gt;Pelmodoro running as a PWA on my desktop and some of the themes you can choose from&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The project is open-source and you can check it out @ &lt;a href="https://github.com/eberfreitas/pelmodoro" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yet another Pomodoro app? Why?
&lt;/h2&gt;

&lt;p&gt;There isn't one reason why, and the answer could be just "because I wanted" 😁 But I also wanted to create something with &lt;a href="https://elm-lang.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Elm&lt;/strong&gt;&lt;/a&gt;, a language I've been using daily for the last year and a half, but that I have never used to build something from my own.&lt;/p&gt;

&lt;p&gt;Besides, I was using &lt;a href="https://habitica.com/" rel="noopener noreferrer"&gt;Habitica&lt;/a&gt; (an RPG game like that helps you achieve your goals and daily tasks) to track my productivity but I felt it was overkill. The idea was to replace Habitica building some of the features that made sense for me into the Pomodoro app, mainly the round rating system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcjzw3llh5c0yu2bka3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcjzw3llh5c0yu2bka3g.png" alt="Calendar with stats"&gt;&lt;/a&gt; &lt;br&gt;
&lt;em&gt;The calendar @ the stats screen also dubs as a graph showing your most productive days, inspired by GitHub's graph&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it work
&lt;/h2&gt;

&lt;p&gt;The main tool I used to build the app was the &lt;a href="https://elm-lang.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Elm&lt;/strong&gt;&lt;/a&gt; language and its ecosystem. It is not a large ecosystem, but it offers lots of quality packages that really surprised me during development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Elm&lt;/strong&gt; is a functional language, strongly typed and pure (with controlled side effects) targeted at front-end development. Although it is not popular, I was impressed to see that most of the problems I needed to solve were already solved by the community.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the timer rendering I used SVG and the excellent &lt;a href="https://package.elm-lang.org/packages/elm/svg/latest/" rel="noopener noreferrer"&gt;official package&lt;/a&gt; to create and handle SVG documents;&lt;/li&gt;
&lt;li&gt;I used &lt;a href="https://package.elm-lang.org/packages/elm/svg/latest/" rel="noopener noreferrer"&gt;elm-css&lt;/a&gt; for the CSS, which allowed me to write safe and dynamic styles;&lt;/li&gt;
&lt;li&gt;For dates handling I used the &lt;a href="https://package.elm-lang.org/packages/justinmimbs/date/latest/" rel="noopener noreferrer"&gt;date&lt;/a&gt; package;&lt;/li&gt;
&lt;li&gt;The calendar on the stats area was easily solved using the &lt;a href="https://package.elm-lang.org/packages/abradley2/elm-calendar/latest/" rel="noopener noreferrer"&gt;calendar&lt;/a&gt; package.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For some of the features, I had to use JavaScript, mainly the Spotify integration. Luckily Spotify has a &lt;a href="https://developer.spotify.com/documentation/web-api/" rel="noopener noreferrer"&gt;reasonlably complete documentation&lt;/a&gt; for its API. After fighting the &lt;a href="https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce" rel="noopener noreferrer"&gt;PKCE&lt;/a&gt; auth system, developing the integration was easy.&lt;/p&gt;

&lt;p&gt;To persist the app's state I used both &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage" rel="noopener noreferrer"&gt;localStorage&lt;/a&gt; (for settings and the timer state) and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API" rel="noopener noreferrer"&gt;IndexedDB&lt;/a&gt; (to persist usage stats). Instead of using the IndexedDB API directly, I used &lt;a href="https://dexie.org/" rel="noopener noreferrer"&gt;Dexie&lt;/a&gt; which abstracts most of the IndexedDB complexities.&lt;/p&gt;

&lt;p&gt;To play sounds I used the &lt;a href="https://howlerjs.com/" rel="noopener noreferrer"&gt;howler.js&lt;/a&gt; lib.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbqigf35j6xoe8zk6cwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbqigf35j6xoe8zk6cwl.png" alt="Rounds rating"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Rate your work rounds and check your stats&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it beautiful
&lt;/h2&gt;

&lt;p&gt;After being satisfied with the features and the way everything looked and worked, I showed my code to some people that gave me valuable feedback, mainly about my code structure. In about two days I refactored my app's structure completely. When I was done I had a PR &lt;a href="https://twitter.com/eber_freitas/status/1418434236084797443" rel="noopener noreferrer"&gt;adding 5,934 lines and removing 3,756&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If that was a JavaScript project, that would be a very daunting PR, but I'm using Elm so refactors are safe and cheap. If it compiles it probably works as intended, so I could just merge the PR without blinking twice.&lt;/p&gt;

&lt;p&gt;The original code structure grew very organically during development, which produced a functional code but was ill-organized. One example was that I was separating &lt;code&gt;Model&lt;/code&gt;, &lt;code&gt;Msg&lt;/code&gt;, and &lt;code&gt;Types&lt;/code&gt; on different modules. The idea was to avoid &lt;a href="https://github.com/elm/compiler/blob/9d97114702bf6846cab622a2203f60c2d4ebedf2/hints/import-cycles.md" rel="noopener noreferrer"&gt;import cycles&lt;/a&gt;, but that was just evidence that my code needed better structure.&lt;/p&gt;

&lt;p&gt;Looking at the &lt;a href="https://github.com/rtfeldman/elm-spa-example" rel="noopener noreferrer"&gt;Real World&lt;/a&gt; application I could see that there were better ways to structure my modules using nested TEAs and keeping the &lt;code&gt;Main&lt;/code&gt; module as a hub for everything in the app.&lt;/p&gt;

&lt;p&gt;My original &lt;code&gt;update&lt;/code&gt; function &lt;a href="https://github.com/eberfreitas/pelmodoro/blob/6d4a9e16b254d6b27fd2d5c8699657bbcb6b226d/src/Main.elm#L465" rel="noopener noreferrer"&gt;was massive&lt;/a&gt;, but after separating messages for each &lt;a href="https://github.com/eberfreitas/pelmodoro/tree/main/src/Page" rel="noopener noreferrer"&gt;"page"&lt;/a&gt; I ended up with a more organized, contained, and easy to understand code.&lt;/p&gt;

&lt;p&gt;There is a lot to talk about code patterns with Elm so I would recommend reading &lt;a href="https://sporto.github.io/elm-patterns/" rel="noopener noreferrer"&gt;Elm patterns&lt;/a&gt; for a more in-depth study.&lt;/p&gt;

&lt;p&gt;I also implemented a few stylistic decisions to standardize my code such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid exposing constructors in module definitions;&lt;/li&gt;
&lt;li&gt;Avoid exposing functions and types when importing modules;&lt;/li&gt;
&lt;li&gt;When aliasing a module, use the module's own name, mimicking Elixir's &lt;code&gt;alias&lt;/code&gt;. Ex.: &lt;code&gt;Html.Attributes as Attributes&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In case of name conflicts a) don't alias at all or b) join module's names. Ex.: &lt;code&gt;Svg.Attributes as SvgAttributes&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Prefix every view function with &lt;code&gt;view&lt;/code&gt; 👀&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea behind most of these was to make the code more explicit, making it clear where types and functions are coming from as well as their effects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8yzlj4wwc188x661peh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8yzlj4wwc188x661peh.png" alt="Most productive hours"&gt;&lt;/a&gt; &lt;br&gt;
&lt;em&gt;Monthly stats, including your most productive hours&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Although I did this big refactor I know my code structure and design could improve at various places, but I want to finish the project. I feel like software in general is never really done, except for a few outliers, so I need to stop investing so much time on this project that is already working very well for me. That way I can invest my time on another side project that will suck out all my free time 🤡&lt;/p&gt;

&lt;p&gt;In general, I'm very satisfied with the final result and have been using the app daily. With some luck other people will find it useful as well and if you are one of those people I'll be extremely happy to know 😊&lt;/p&gt;

</description>
      <category>functional</category>
      <category>productivity</category>
      <category>elm</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Elm in the server (or anywhere else) with promises</title>
      <dc:creator>Éber Freitas Dias</dc:creator>
      <pubDate>Mon, 04 Jan 2021 14:20:44 +0000</pubDate>
      <link>https://dev.to/eberfreitas/elm-in-the-server-or-anywhere-else-with-promises-5eoj</link>
      <guid>https://dev.to/eberfreitas/elm-in-the-server-or-anywhere-else-with-promises-5eoj</guid>
      <description>&lt;p&gt;Elm was created to run on the browser, but every once in a while someone will ask about how to run Elm in a server environment.&lt;/p&gt;

&lt;p&gt;At my current job, we needed to sync several clients and persist that shared state somewhere, so we thought it would be a good idea if the server could act like another client that could persist that state in a centralized place.&lt;/p&gt;

&lt;p&gt;For that, we created a Node/Express server to run our Elm code and at first, it was very hackish.&lt;/p&gt;

&lt;p&gt;In a server-like environment, you mostly always have a request and a response tied together. You ask for something and you might get what you requested or an error. It doesn't matter, for every request, there is a response.&lt;/p&gt;

&lt;p&gt;But Elm doesn't work like that if you wanna talk to the outside world. Yes, you can use &lt;a href="https://guide.elm-lang.org/interop/ports.html"&gt;ports&lt;/a&gt; for outside communication, but ports follow the actor model of message passing. So contrary to the request/response nature of server communication, you can only send and receive messages in Elm. That might sound like the same thing but it is not. You can receive a message without ever sending one in the first place. Or send a message without the need to wait for a message back. You can send a message and receive multiple messages back and so on. There is no coupling between sending and receiving a message and that makes Elm kinda unsuitable for a server software where request/response messages are tied.&lt;/p&gt;

&lt;p&gt;After looking for better solutions I came across &lt;a href="https://discourse.elm-lang.org/t/imitating-synchronicity-with-ports/1930"&gt;this post&lt;/a&gt; in the forums where the user &lt;a href="https://discourse.elm-lang.org/u/joakin"&gt;joakin&lt;/a&gt; made a clever suggestion: just send the &lt;strong&gt;response&lt;/strong&gt; object from the JavaScript side to a port and send it back through another port when replying to whatever it was requesting. Use the response object to send a proper response to the right client and there you go. You can see an example of that &lt;a href="https://github.com/joakin/node-elm-server"&gt;on this helpful repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That is something I didn't know: you can pass any JavaScript value as a &lt;a href="https://package.elm-lang.org/packages/elm/json/latest/Json-Decode#Value"&gt;&lt;code&gt;Json.Decode.Value&lt;/code&gt;&lt;/a&gt; to Elm, even functions. Of course, you can't do much with them inside Elm but in this case, it helps to tie a specific function call to the message we will send back.&lt;/p&gt;

&lt;p&gt;The idea is great and helps us to have some type of tied request/response flow. The problem is when we needed to test the integration. It was easier to bypass all the server stuff and focus on the interoperation between Node and Elm directly. Or even worse, what if the software we were writing wasn't a Node/Express server at all? That is when my boss and co-worker &lt;a href="https://twitter.com/nateabele"&gt;Nate&lt;/a&gt; suggested we used promises. Instead of sending the response object from Express to Elm, we could send the resolve function from a promise!&lt;/p&gt;

&lt;p&gt;I have made a fork from the example code above with these changes. You can check it out &lt;a href="https://github.com/eberfreitas/node-elm-server"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the &lt;a href="https://github.com/eberfreitas/node-elm-server/blob/master/src/Server.elm"&gt;Elm side&lt;/a&gt;, nothing much has changed. I just made a few naming changes to better reflect the new nature of the interoperation with the JavaScript code. But other than that, we didn't have to change much to make this approach work as both the previous response object that was being sent from Express and the new resolve function from the promise are both just &lt;code&gt;Json.Decode.Value&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;The real magic is on the &lt;a href="https://github.com/eberfreitas/node-elm-server/blob/master/index.js"&gt;JavaScript code&lt;/a&gt;. It is a little bit more complex but it decouples the Elm code and ports from Express itself, making it possible to use that approach virtually anywhere. Here is the bit that makes everything work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;http&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(([{&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&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="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, it is possible to use Elm in the server, and I would argue that with that approach if you need some kind of tied request/response integration, you can use Elm anywhere where you can use Node. &lt;strong&gt;But is it useful?&lt;/strong&gt; In our case, where we wanted to use most of the code from our client on the server it was a total win, but I would think twice if I wanted to build a full server with Elm as it just doesn't have all the things you will need to make it a good developing experience, although it would be possible.&lt;/p&gt;

&lt;p&gt;Maybe &lt;a href="https://youtu.be/ZnYa99QoznE?t=4755"&gt;Roc&lt;/a&gt; will be the language we will use for cases like that. Can't wait for it!&lt;/p&gt;

&lt;p&gt;So, what do you think about this approach? Have you done something similar or vastly different to solve the same problem?&lt;/p&gt;

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

</description>
      <category>elm</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Comparing Elm to Ember Octane and React</title>
      <dc:creator>Éber Freitas Dias</dc:creator>
      <pubDate>Tue, 12 May 2020 21:08:04 +0000</pubDate>
      <link>https://dev.to/eberfreitas/comparing-elm-to-ember-octane-and-react-1in2</link>
      <guid>https://dev.to/eberfreitas/comparing-elm-to-ember-octane-and-react-1in2</guid>
      <description>&lt;p&gt;Today I stumbled on this article "&lt;a href="https://www.pzuraq.com/comparing-ember-octane-and-react/"&gt;Comparing Ember Octane and React&lt;/a&gt;" on Hacker News.&lt;/p&gt;

&lt;p&gt;The article goes to demonstrate how the same application can be built both with React and Ember, going into implementation details and drawing some conclusions from it. The app is a simple Hacker News search that you can test yourself here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codesandbox.io/s/github/the-road-to-learn-react/hacker-stories/tree/hs/Async-Await-in-React"&gt;React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://glitch.com/~comparing-ember-octane-and-react"&gt;Ember&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end of the article, the author (&lt;a href="https://www.pzuraq.com/author/pzuraq/"&gt;Chris Garrett&lt;/a&gt;, which is an Ember Core team member) writes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In writing this post, I feel like I got to experience React with hooks much more deeply than the research I've done before, and I enjoyed learning them and working with them. It is an interesting programming model, and while I'm not entirely sold yet (I think I'd still prefer something more akin to &lt;strong&gt;Elm&lt;/strong&gt; personally) I can definitely see why people like them, and what the advantanges are.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That had me wondering: what the Elm version of the same app would look like? So I tried to build it! You can see the ending result &lt;a href="https://ellie-app.com/8Rn7dL9RKyWa1"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like in the original post, let's take a deeper look at what is going on here.&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting started
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;port&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="kt"&gt;Main&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Browser&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Dom&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Dom&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Html&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strong&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Attributes&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Events&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decoder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt;


&lt;span class="k"&gt;port&lt;/span&gt; &lt;span class="n"&gt;sendQuery&lt;/span&gt; &lt;span class="p"&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;Cmd&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how most Elm applications (and files) start. You define the file's module name and explicitly declares what you want to expose and import from other modules. Elm has it's own package manager and when you create a new project, it will install a few basic packages to get you going. We also had to install some extra packages like &lt;code&gt;elm/json&lt;/code&gt; and &lt;code&gt;elm/http&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One particular thing about our module is the fact that we start it by saying &lt;code&gt;port module&lt;/code&gt;. In case you are not familiar with Elm, it is a purely functional language that can't have side effects. That means we can't, for instance, set things to &lt;code&gt;localStorage&lt;/code&gt; from our Elm code. That is where ports come in, but we will talk about it later. At the end of this section, we declare a port named &lt;code&gt;sendQuery&lt;/code&gt; that we will use later on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comments&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&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;input&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastSearch&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stories&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Stories&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Stories&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt;
    &lt;span class="o"&gt;|&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;Stories&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;Story&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NoOp&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;GotInput&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;Search&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Dismiss&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;GotResults&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Stories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have our types definitions. Elm is a strong and static typed language. That means we can create our types to help model the application. First, we have two alias types: &lt;code&gt;Story&lt;/code&gt; and &lt;code&gt;Model&lt;/code&gt;. An alias type just gives a nickname to some other typed structure. That way we can use the compiler to help us write the correct structure every time.&lt;/p&gt;

&lt;p&gt;Later we have some custom types: &lt;code&gt;Stories&lt;/code&gt; and &lt;code&gt;Msg&lt;/code&gt;. Those types will help us to keep a better understanding of our application's state and what we should do about it.&lt;/p&gt;

&lt;h1&gt;
  
  
  The TEA
&lt;/h1&gt;

&lt;p&gt;The TEA (or The Elm Architecture) is a way to describe how most Elm applications work in terms of how the data flows through our code. It consists of a few basic concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have one global state;&lt;/li&gt;
&lt;li&gt;That state is rendered using some &lt;code&gt;view&lt;/code&gt; function;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;view&lt;/code&gt; can send messages to some kind of &lt;code&gt;update&lt;/code&gt; function (picture a button click or form submission);&lt;/li&gt;
&lt;li&gt;Finally, the &lt;code&gt;update&lt;/code&gt; mutates the state that is re-rendered by the &lt;code&gt;view&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is it! So let's build those functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Msg&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="p"&gt;(&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;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&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;msg&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;NoOp&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;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;GotInput&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="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;|&lt;/span&gt; &lt;span class="n"&gt;input&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="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;Search&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;if&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;input&lt;/span&gt; &lt;span class="o"&gt;/=&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;lastSearch&lt;/span&gt; &lt;span class="k"&gt;then&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;|&lt;/span&gt; &lt;span class="n"&gt;lastSearch&lt;/span&gt; &lt;span class="o"&gt;=&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;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;request&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;input&lt;/span&gt;
                    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sendQuery&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;input&lt;/span&gt;
                    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;focusSearch&lt;/span&gt;
                    &lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;else&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;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;Dismiss&lt;/span&gt; &lt;span class="n"&gt;id_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt;
                &lt;span class="n"&gt;stories_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                    &lt;span class="k"&gt;case&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;stories&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
                        &lt;span class="kt"&gt;Stories&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                            &lt;span class="kt"&gt;Stories&lt;/span&gt; &lt;span class="p"&gt;(&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;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&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="n"&gt;id_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                        &lt;span class="n"&gt;_&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="n"&gt;stories&lt;/span&gt;
            &lt;span class="k"&gt;in&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;|&lt;/span&gt; &lt;span class="n"&gt;stories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stories_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;GotResults&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
                &lt;span class="kt"&gt;Err&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="k"&gt;let&lt;/span&gt;
                        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                            &lt;span class="kt"&gt;Debug&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error"&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
                    &lt;span class="k"&gt;in&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;|&lt;/span&gt; &lt;span class="n"&gt;stories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="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;|&lt;/span&gt; &lt;span class="n"&gt;stories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="p"&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;Msg&lt;/span&gt;
&lt;span class="n"&gt;view&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;div&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&lt;/span&gt;
        &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My Hacker Stories"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;searchForm&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;input&lt;/span&gt;
            &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;stories&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;stories&lt;/span&gt;


&lt;span class="n"&gt;searchForm&lt;/span&gt; &lt;span class="p"&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;List&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;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;searchForm&lt;/span&gt; &lt;span class="n"&gt;input_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;search"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;strong&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search:"&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="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;search"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;input_&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onInput&lt;/span&gt; &lt;span class="kt"&gt;GotInput&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text"&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="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="kt"&gt;Search&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Submit"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hr&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="n"&gt;stories&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Stories&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;Html&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;stories&lt;/span&gt; &lt;span class="n"&gt;stories_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;stories_&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Loading&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;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading ..."&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="kt"&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;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Something went wrong ..."&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="kt"&gt;Stories&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;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No results."&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="kt"&gt;Stories&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&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;map&lt;/span&gt; &lt;span class="n"&gt;storyItem&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;


&lt;span class="n"&gt;storyItem&lt;/span&gt; &lt;span class="n"&gt;i&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="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&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="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="p"&gt;]&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;"&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromInt&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comments&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="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromInt&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;points&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="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Dismiss&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dismiss"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have an &lt;code&gt;update&lt;/code&gt; function that will receive our model and a message. Remember our types &lt;code&gt;Model&lt;/code&gt; and &lt;code&gt;Msg&lt;/code&gt;? We are going to use them here. We need to check which &lt;code&gt;Msg&lt;/code&gt; we are getting and make the appropriate changes to the &lt;code&gt;Model&lt;/code&gt;. And if you are paying attention you can see that we don't just return our &lt;code&gt;Model&lt;/code&gt;, but a &lt;code&gt;Cmd msg&lt;/code&gt; type (command). Remember when I said Elm can't have side effects? To solve that we have commands, which are a special type that we can handle to the Elm runtime to solve for us. It can be, for instance, an HTTP request like we are doing when &lt;code&gt;Msg&lt;/code&gt; is &lt;code&gt;Search&lt;/code&gt;. More on that later...&lt;/p&gt;

&lt;p&gt;After that, we have a few different functions that will return the type &lt;code&gt;Html&lt;/code&gt;. That is different from returning actual HTML, but that is how we implement templates and components with Elm. Using plain functions! The Elm runtime will take care of things and render proper HTML from that.&lt;/p&gt;

&lt;p&gt;Now, let's wire it all together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Program&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="kt"&gt;Msg&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;Browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;focusSearch&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="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="kt"&gt;Sub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;main&lt;/code&gt; function is the entry point of our application. It is what the Elm runtime will look for and run once it kicks in. Here we are explicitly saying which functions our application will use for each stage of TEA. The &lt;code&gt;init&lt;/code&gt; key is a function that should set up the initial model. Keys &lt;code&gt;view&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; are pretty self-explanatory by now. Finally, we have &lt;code&gt;subscriptions&lt;/code&gt; that we won't use for this app but if you are interested, take a look at the &lt;a href="https://guide.elm-lang.org/"&gt;elm guide&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The missing stuff
&lt;/h1&gt;

&lt;p&gt;Finally we have a few extra functions that will make our interaction with the application more dynamic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;focusSearch&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;focusSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;NoOp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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;focus&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;search"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&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;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://hn.algolia.com/api/v1/search?query="&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expectJson&lt;/span&gt; &lt;span class="kt"&gt;GotResults&lt;/span&gt; &lt;span class="n"&gt;resultsDecoder&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="n"&gt;resultsDecoder&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Decoder&lt;/span&gt; &lt;span class="kt"&gt;Stories&lt;/span&gt;
&lt;span class="n"&gt;resultsDecoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hits"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&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;storyDecoder&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;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;andThen&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;succeed&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="kt"&gt;Stories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;storyDecoder&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Decoder&lt;/span&gt; &lt;span class="kt"&gt;Story&lt;/span&gt;
&lt;span class="n"&gt;storyDecoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map6&lt;/span&gt; &lt;span class="kt"&gt;Story&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;objectID"&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title"&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author"&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url"&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;num_comments"&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;points"&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function &lt;code&gt;focusSearch&lt;/code&gt; is just a helper function that returns a command to inform the Elm runtime to focus on an element with a specific &lt;code&gt;id&lt;/code&gt; and that is it. That one I straight copied from the Elm guide.&lt;/p&gt;

&lt;p&gt;The real important function comes next: &lt;code&gt;request&lt;/code&gt;. It receives a query string and creates a command that runs an HTTP request. This is where Elm shines for me. After making a request the runtime will send a new message for the application with some data. In our case we are telling the runtime to return the data with the &lt;code&gt;GotResults&lt;/code&gt; message, expecting a JSON that can be successfully decoded with the &lt;code&gt;resultsDecoder&lt;/code&gt; function. See, everything in Elm is typed and we can't just receive arbitrary data from the server. How would the compiler know which type of data are we dealing with? That is why we have to decode the JSON that we get, making it fit at a specific type. In our case, we need the JSON to return a valid &lt;code&gt;Stories&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;If you take a look at the way we handle the &lt;code&gt;GotResults&lt;/code&gt; message on our &lt;code&gt;update&lt;/code&gt; function, you will see that the returning data can either be &lt;code&gt;Ok ...&lt;/code&gt; or an &lt;code&gt;Err ...&lt;/code&gt;. An &lt;code&gt;Err&lt;/code&gt; may occur if the HTTP request fails or if the JSON decoding fails.&lt;/p&gt;

&lt;h1&gt;
  
  
  We still need JS after all...
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;/* you can style your program here */&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Elm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;searchTerm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Elm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;searchTerm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important bit about the HTML/JS part of our app is how we start it. On the &lt;code&gt;init&lt;/code&gt; function call we can pass the value of the current data stored at the &lt;code&gt;localStorage&lt;/code&gt; to our application. Take a look at the &lt;code&gt;init&lt;/code&gt; function on the Elm side to see how we handle that.&lt;/p&gt;

&lt;p&gt;After that, we use the &lt;code&gt;sendQuery&lt;/code&gt; port to save the search query every time a new search occurs. Take a look at the &lt;code&gt;Search&lt;/code&gt; message handling we do on the &lt;code&gt;update&lt;/code&gt; function to see the use to the &lt;code&gt;sendQuery&lt;/code&gt; port we defined right at the beginning of our module.&lt;/p&gt;

&lt;h1&gt;
  
  
  Takeaways
&lt;/h1&gt;

&lt;p&gt;I have no real experience with React or Ember so this section won't be as well informed or in-depth as in the original article is. But let's take a look at how Elm solves some of our problems in a very efficient and easy way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom types are a game-changer
&lt;/h2&gt;

&lt;p&gt;The React implementation on the &lt;code&gt;storiesReducer&lt;/code&gt; function will do something like what our &lt;code&gt;update&lt;/code&gt; function does. The real problem here is that it uses plain strings as keys for the possible actions it can execute. That is fine until you need more messages/actions.&lt;/p&gt;

&lt;p&gt;Because we are using an actual custom type as our message (we could be using strings but that wouldn't help), we need to handle every possible message that there is. If we need more messages we can just add them to our &lt;code&gt;Msg&lt;/code&gt; type and the compiler will politely tell us about all the places where we need to handle that new message if we miss something.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom types are a game-changer ²
&lt;/h2&gt;

&lt;p&gt;Both on the React and Ember apps you will see that the "model" has a few flags like &lt;code&gt;isLoading&lt;/code&gt; or &lt;code&gt;isError&lt;/code&gt;. All that those flags are doing is informing the state of the stories we are trying to load. See how we always need to worry about resetting the values of those flags so we don't end up with a view that says that we have an error and we are loading at the same time. Nothing is preventing that from happening...&lt;/p&gt;

&lt;p&gt;We can solve that by using a custom type that can represent the state of those stories only once at a time. It can't be &lt;code&gt;Loading&lt;/code&gt; and &lt;code&gt;Error&lt;/code&gt; at the same time, so we have certainty that our view will always render the right thing no matter what.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON decoding
&lt;/h2&gt;

&lt;p&gt;We have a bug in this app. See... A story title or author can be a &lt;code&gt;null&lt;/code&gt; value coming back from the API call. If you open up the React or Ember apps and search for "elmish" for instance, you will get a few funny looking lines. That is because JavaScript won't stop you from accessing data that don't exist on a given object, rendering a pretty confusing and uninformative list of... things.&lt;/p&gt;

&lt;p&gt;That can't happen with Elm. Besides the fact that we can use alias types to inform our compiler about the shape of some structures, when receiving data from the outside world it has to pass through a decoding process and that decoding can either work or fail: Elm will force us to handle both situations or it won't compile our program. Search for "elmish" on the Elm version of the app and you will see the message "Something went wrong ...". That is because our decoder only decodes strings for the &lt;code&gt;title&lt;/code&gt; key, and if that key is &lt;code&gt;null&lt;/code&gt; on the JSON side, it won't decode at all.&lt;/p&gt;

&lt;p&gt;We could then update our decoder to handle those situations, maybe making the &lt;code&gt;title&lt;/code&gt; key a &lt;code&gt;Maybe String&lt;/code&gt;, and that would force us to handle the fact the &lt;code&gt;title&lt;/code&gt; can either be &lt;code&gt;Just ...&lt;/code&gt; something or &lt;code&gt;Nothing&lt;/code&gt; in our &lt;code&gt;view&lt;/code&gt; function. We could never reproduce those silly and confusing lines you get from using "plain" JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple take
&lt;/h2&gt;

&lt;p&gt;Hooks, components, tracked properties, actions, and so on... JS-land apps can have a lot of concepts that require time to learn and master. Elm, on the other hand, is pretty simple. Despite its somewhat cryptic syntax, if you never dealt with anything like it, Elm introduces very few concepts: everything is a function, and the way you make your application work is through the iteration of TEA, just like that.&lt;/p&gt;




&lt;p&gt;I fell like I'm having a very superficial take on top of such a well informed and well-written article like the one this is based on, but hopefully, I succeeded at showing how Elm would solve similar problems pointing at the exciting things it brings to the table.&lt;/p&gt;

&lt;p&gt;What am I missing from my list of takeaways? Is there any place where the React/Ember solutions are better? Please, let me know in the comments section. Cheers!&lt;/p&gt;

</description>
      <category>elm</category>
      <category>ember</category>
      <category>react</category>
      <category>functional</category>
    </item>
    <item>
      <title>Elixir for PHP developers - Programming paradigm</title>
      <dc:creator>Éber Freitas Dias</dc:creator>
      <pubDate>Tue, 01 Oct 2019 03:04:16 +0000</pubDate>
      <link>https://dev.to/eberfreitas/elixir-for-php-developers-programming-paradigm-4ii9</link>
      <guid>https://dev.to/eberfreitas/elixir-for-php-developers-programming-paradigm-4ii9</guid>
      <description>&lt;p&gt;When I want to learn something new I try to find some kind of material comparing it to something that I already know so I can see the pros and cons and decide if I should invest my time on it.&lt;/p&gt;

&lt;p&gt;I come from the PHP world and fell in love with Elixir so my idea here is to compare some aspects of those languages and show how they are different (or similar) and maybe help you make a decision to learn more about it. I hope you will find that Elixir is a super fun language to work with!&lt;/p&gt;

&lt;p&gt;By the way, I'm a beginner in the Elixir world. This is the perspective from someone learning it as we go so take that into account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elixir is a functional programming language
&lt;/h2&gt;

&lt;p&gt;The first big difference between PHP and Elixir is that Elixir is a pure FP (functional programming) language. PHP, on the other hand, is a multi-paradigm language, where you can solve problems using different paradigms even though OOP (object-oriented programming) is pretty dominant these days.&lt;/p&gt;

&lt;p&gt;And what does FP means? The theory can get really dense, and you might wanna check the &lt;a href="https://en.wikipedia.org/wiki/Functional_programming"&gt;Wikipedia&lt;/a&gt; article for a more elaborated description, but in a nutshell and for the purposes of this comparison, it means there are &lt;strong&gt;no objects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An object in OOP is (among other things) when you bundle data and functionality together: on the same object, you have the state and the methods to affect that state.&lt;/p&gt;

&lt;p&gt;But in functional programming, those are separated things and all you get are functions that manipulate data. Let's take a look at how that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;DataLayer&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$email&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="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'john.doe@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The somewhat equivalent of that code in Elixir looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="s2"&gt;"john.doe@example.com"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a lot going on here. The syntax is kinda alien compared to the PHP counterpart. No brackets, and what is that assignment on the function definition? Well, we will get there but just to clarify, that is &lt;strong&gt;not&lt;/strong&gt; an assignment.&lt;/p&gt;

&lt;p&gt;What we did here was to create a &lt;code&gt;struct&lt;/code&gt; which is a glorified &lt;code&gt;map&lt;/code&gt;. A &lt;code&gt;map&lt;/code&gt; is similar to an associative array in PHP where you have keys and values. The difference between a &lt;code&gt;map&lt;/code&gt; and a &lt;code&gt;struct&lt;/code&gt; is that with the &lt;code&gt;struct&lt;/code&gt; you can &lt;strong&gt;struct&lt;/strong&gt;ure how the data will look like, defining keys and even default values (you might be thinking "uhm, that looks like an object" but &lt;strong&gt;it is not&lt;/strong&gt;, it is just data).&lt;/p&gt;

&lt;p&gt;Another thing you might have noticed is that we don't have any kind of inheritance. In the PHP code, it is assumed that the &lt;code&gt;save&lt;/code&gt; method comes from the &lt;code&gt;DataLayer&lt;/code&gt; class from which the &lt;code&gt;User&lt;/code&gt; class extends but in the Elixir code the &lt;code&gt;save&lt;/code&gt; function is just calling another function from another module (&lt;code&gt;Repo&lt;/code&gt; being the module) to persist the data to the database.&lt;/p&gt;

&lt;p&gt;In FP you have data and functions all the way down and your work is to &lt;strong&gt;compose&lt;/strong&gt; those things to make bigger things that can also be composed onto other things.&lt;/p&gt;

&lt;h2&gt;
  
  
  But PHP also has functions...
&lt;/h2&gt;

&lt;p&gt;The Elixir code could be roughly translated to PHP like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;DataLayer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'john.doe@example.com'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So PHP can do FP right? Well, right... I guess? Like I said at the beginning, Elixir is a &lt;strong&gt;pure&lt;/strong&gt; FP language. That means that there are no "escape hatches" from the FP world when using Elixir.&lt;/p&gt;

&lt;p&gt;In PHP you can certainly try to use a "functional style" of code but it will never be real FP. You might get "lazy" and just take advantage of the multi-paradigm nature of the language to solve some problems in other ways and in fact, that would be easier in PHP because it is not an FP language.&lt;/p&gt;

&lt;p&gt;Also, FP is not only defined by the lack of objects. If you were curious enough to take a look at that Wikipedia article you might have seen that the FP paradigm includes other things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First-class functions&lt;/li&gt;
&lt;li&gt;Total functions&lt;/li&gt;
&lt;li&gt;Pure functions&lt;/li&gt;
&lt;li&gt;Data immutability&lt;/li&gt;
&lt;li&gt;Recursion&lt;/li&gt;
&lt;li&gt;Heavy use of &lt;del&gt;drugs&lt;/del&gt; mathematical theory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Among many other things...&lt;/p&gt;

&lt;p&gt;Some of that you might even have in PHP. First-class functions entered the language with closures on version 5.3. Other things you definitely won't have like &lt;strong&gt;data immutability&lt;/strong&gt; which is a huge aspect of FP.&lt;/p&gt;

&lt;h2&gt;
  
  
  And how is it any better?
&lt;/h2&gt;

&lt;p&gt;Now you have a rough idea of what FP is and how it is different from OOP but is it any better than OOP? Yes and no. Some people might claim that each paradigm has its place in the programming world trying to solve different problems but at the end of the day, FP is just a different way to look at programming.&lt;/p&gt;

&lt;p&gt;Instead of thinking about objects and their attributes and methods, you only think about data and how to transform that data with functions. It is a simpler outlook but a very powerful one.&lt;/p&gt;

&lt;p&gt;Without strong patterns and consistency OO programs can quickly become unmaintainable. With FP you can avoid a lot of those pitfalls writing simpler code that is easier to write and refactor. Don't get me wrong, you can still screw up writing FP but some common problems in the way you architect programs with OOP are non-existent in FP.&lt;/p&gt;

&lt;p&gt;There are a lot of articles out there that will show you how FP can be a strong paradigm and I suggest you take a look. I know there are a lot of loose ends in this article but I'm just trying to make an interesting introduction. The idea is to dive deeper on some of these concepts in future articles.&lt;/p&gt;

&lt;p&gt;Let me know if you are interested in a specific subject and how that compares to PHP. I might talk about it in my next article.&lt;/p&gt;

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

</description>
      <category>elixir</category>
      <category>php</category>
      <category>beginners</category>
      <category>functional</category>
    </item>
  </channel>
</rss>
