<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Haskell on Calm Engineering</title>
    <link>https://lukastymo.com/tags/haskell/</link>
    <description>Recent content in Haskell on Calm Engineering</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Sun, 25 Jan 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://lukastymo.com/tags/haskell/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Hello, Haskell: Getting Started in 2026</title>
      <link>https://lukastymo.com/posts/025-hello-haskell-a-hands-on-lab-for-2026/</link>
      <pubDate>Sun, 25 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://lukastymo.com/posts/025-hello-haskell-a-hands-on-lab-for-2026/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Read this if you want to:&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;see beginner examples that link Haskell’s syntax to its underlying mental models – types, pattern matching, declarative style and &lt;code&gt;do&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;see examples of Haskell’s distinctive syntax in practice&lt;/li&gt;&#xA;&lt;li&gt;learn what Robin Milner’s work changed in functional programming&lt;/li&gt;&#xA;&lt;li&gt;write and run code as you go&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;In the current AI era, Rust and Python draw the most attention from learners and employers. Haskell, by contrast, remains niche: it trends lower on Google Trends and has far fewer job listings on LinkedIn. When roles do appear, the bar can be high enough that newcomers struggle to get started.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Read this if you want to:&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;see beginner examples that link Haskell’s syntax to its underlying mental models – types, pattern matching, declarative style and &lt;code&gt;do&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;see examples of Haskell’s distinctive syntax in practice&lt;/li&gt;&#xA;&lt;li&gt;learn what Robin Milner’s work changed in functional programming&lt;/li&gt;&#xA;&lt;li&gt;write and run code as you go&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;In the current AI era, Rust and Python draw the most attention from learners and employers. Haskell, by contrast, remains niche: it trends lower on Google Trends and has far fewer job listings on LinkedIn. When roles do appear, the bar can be high enough that newcomers struggle to get started.&lt;/p&gt;&#xA;&lt;p&gt;Meanwhile, LLMs now write a growing share of code, and developers are unusually uncertain about the profession’s direction. Interest in functional programming has also cooled since 2022 across employers and employees. The pragmatic objection recurs: strong FP developers are scarce, and their rates often do not look justified for the work being built.&lt;/p&gt;&#xA;&lt;p&gt;Against that backdrop, hype is a poor guide. Learning tends to last longer when it is driven by intellectual interest rather than short-term demand. Haskell suits readers drawn to type-driven design and compact, algebraic notation.&lt;/p&gt;&#xA;&lt;p&gt;A common observation is that a language may appear strange at first; once learned, other languages can begin to look unfamiliar. The same pattern appears when learning ideas such as type classes and tagless final in Scala: explanations often fail to “click” when the original context has been stripped away. Much of this material was imported from Haskell, adapted with trade-offs and additions, and then presented in isolation; returning to the source often clarifies what the abstraction is doing.&lt;/p&gt;&#xA;&lt;aside class=&#34;not-prose my-6 rounded-md border-l-4 border-slate-200 bg-slate-50 dark:border-slate-600 dark:bg-slate-800 text-slate-800 dark:text-slate-200 px-4 py-3&#34;&gt;&#xA;  &lt;div class=&#34;flex items-start gap-2&#34;&gt;&#xA;    &lt;span class=&#34;mt-[2px] opacity-60 leading-none&#34; aria-hidden=&#34;true&#34;&gt;&#xA;      ✅&#xA;    &lt;/span&gt;&#xA;&#xA;    &lt;div class=&#34;space-y-2 text-sm sm:text-base leading-relaxed&#34;&gt;&#xA;      &lt;div class=&#34;flex items-center gap-2 font-semibold&#34;&gt;Hands-on approach&lt;/div&gt;&#xA;&#xA;      &lt;div class=&#34;&#xA;        [&amp;&gt;p]:m-0&#xA;        [&amp;&gt;ul]:m-0 [&amp;&gt;ul]:list-disc [&amp;&gt;ul]:pl-5&#xA;        [&amp;&gt;ol]:m-0 [&amp;&gt;ol]:list-decimal [&amp;&gt;ol]:pl-5&#xA;        [&amp;&gt;ul&gt;li]:mt-1 [&amp;&gt;ol&gt;li]:mt-1&#xA;        [&amp;&gt;ul&gt;li::marker]:opacity-50&#xA;        [&amp;&gt;ol&gt;li::marker]:opacity-50&#xA;        [&amp;&gt;pre]:m-0 [&amp;&gt;pre]:overflow-x-auto&#xA;        [&amp;_a]:underline [&amp;_a]:underline-offset-2 [&amp;_a]:font-semibold&#xA;&#34;&gt;A hands-on approach works best. These examples work best when they are typed into an editor and executed, so their behavior is visible directly.&lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/aside&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;setting-the-foundations&#34;&gt;Setting the foundations&lt;/h2&gt;&#xA;&#xA;&lt;h3 id=&#34;tooling-and-workspace&#34;&gt;Tooling and workspace&lt;/h3&gt;&#xA;&lt;p&gt;Haskell is often approached a few times over the years. In 2026, the basic setup is clear enough to reduce churn, but tooling still decides whether time goes into learning the language or debugging editors.&lt;/p&gt;&#xA;&lt;p&gt;JetBrains IDEs are often the default for consistent shortcuts and workflow. That works well for Scala in IntelliJ, Python in PyCharm, C++ in CLion, and React/JS in WebStorm. For Haskell, however, there is no comparable “it just works” experience: the plugins evaluated were either obsolete or unreliable, and time can be lost to tooling rather than to concepts.&lt;/p&gt;&#xA;&lt;p&gt;By contrast, VS Code with a Haskell extension is a reliable default. Shortcuts are discoverable via the Command Palette; the UI shows each command’s shortcut. A dedicated learning repository helps isolate experiments. A common pattern is &lt;code&gt;sandbox-&amp;lt;language-name&amp;gt;&lt;/code&gt;, for example &lt;code&gt;sandbox-haskell&lt;/code&gt;, kept private to reduce the risk of accidental disclosure.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;organizing-practice&#34;&gt;Organizing practice&lt;/h3&gt;&#xA;&lt;p&gt;The folder structure used here is:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tree -L 2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── README.md&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── src&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── Books (1)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── codeforces&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── euler&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── finalprojects&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── goals&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── h99&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── spoj&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── Wiki (2)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── stack.yaml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── stack.yaml.lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── test&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └── Spec.hs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The structure separates &lt;code&gt;src/Books&lt;/code&gt; and &lt;code&gt;src/Wiki&lt;/code&gt; to support two loops: working through books and maintaining a personal reference.&lt;/p&gt;&#xA;&lt;p&gt;Book exercises are typically organised as:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; tree -L 2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── ProgrammingInHaskell&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ├── Ch01.hs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ├── Ch02.hs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ├── Ch04.hs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └── Ch05.hs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A wiki reference is typically organised as:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; Algorithms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └── Sort.hs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Haskell syntax is close to mathematical notation, so some algorithms end up looking notably close to pseudocode. The wiki can serve as a reference: “What does idiomatic Haskell look like?” Over time it reduces the cost of relearning details and limits exposure to low-quality patterns from LLMs.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;installing-the-toolchain&#34;&gt;Installing the toolchain&lt;/h3&gt;&#xA;&lt;p&gt;Installation is OS-specific. On Fedora, the setup was:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;gmp-devel&lt;/code&gt; provides the headers for the GMP library, which GHC and many packages rely on for efficient big-integer arithmetic.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; sudo dnf install gmp-devel&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;GHCup is the de facto toolchain installer/manager for Haskell: it can install and switch between versions of GHC, Cabal, Stack, and HLS.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl --proto &amp;#39;=https&amp;#39; --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The compiler version used here is 9.8.4.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghcup install ghc 9.8.4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghcup set ghc 9.8.4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A first Haskell file typically uses the &lt;code&gt;.hs&lt;/code&gt; extension. The examples below use &lt;code&gt;./src/Hello.hs&lt;/code&gt;, opened in VS Code to enable editor feedback and type hints.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;ai-as-an-auxiliary-tool&#34;&gt;AI as an auxiliary tool&lt;/h2&gt;&#xA;&lt;p&gt;Copilot is generally better to avoid at this point: it reduces active thinking and slows the formation of a mental model.&lt;/p&gt;&#xA;&lt;p&gt;LLMs are most useful as a secondary tool for troubleshooting tooling, installation, and confusing error messages.&lt;/p&gt;&#xA;&lt;p&gt;After solving an exercise, comparing it with an LLM solution can also be useful.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;h2 id=&#34;first-steps-in-ghci&#34;&gt;First steps in GHCi&lt;/h2&gt;&#xA;&lt;p&gt;With a Haskell extension in VS Code and GHC installed, a minimal module is enough to confirm that the toolchain works end to end. Early on, keeping examples in a single file and loading them via &lt;code&gt;ghci&lt;/code&gt; lets you iterate quickly without a full build.&lt;/p&gt;&#xA;&lt;p&gt;GHCi is Haskell&amp;rsquo;s interactive REPL: it loads modules, type-checks and evaluates expressions, and supports fast iteration. For example:&lt;/p&gt;&#xA;&lt;p&gt;./src/Hello.hs:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;add x y = x + y&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A typical session starts from the &lt;code&gt;src&lt;/code&gt; directory:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cd src&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghci&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once GHCi starts, the file is loaded:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;load&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Hello&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hs&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Shorthand: &lt;code&gt;:l Hello.hs&lt;/code&gt;. After loading the file, the &lt;code&gt;add&lt;/code&gt; function is available. After editing the file, it is reloaded with:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reload&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or the shorthand &lt;code&gt;:r&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The function can then be called by name:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;add 1 2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Output: 3&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;verifying-the-setup&#34;&gt;Verifying the setup&lt;/h3&gt;&#xA;&lt;p&gt;A short sanity check that the environment is wired correctly:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ghci&lt;/code&gt; runs in the &lt;code&gt;src&lt;/code&gt; directory&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;:load Hello.hs&lt;/code&gt; loads the file&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;add 1 2&lt;/code&gt; returns &lt;code&gt;3&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;types-as-the-surface-of-programs&#34;&gt;Types as the surface of programs&lt;/h2&gt;&#xA;&lt;p&gt;In Haskell, everything is expressed in terms of values and functions. There’s no mutation in the “update a variable” sense, which is what people mean when they call Haskell a &lt;em&gt;pure&lt;/em&gt; functional language. By contrast, in a multi-paradigm language like Scala, it’s possible to write &lt;code&gt;var x = 5&lt;/code&gt; and later update it to &lt;code&gt;x = 6&lt;/code&gt;. That style is not how Haskell code is structured, and it changes how programs are reasoned about.&lt;/p&gt;&#xA;&lt;p&gt;A second function helps clarify terminology. The distinction between “method” and “function” matters in Haskell’s model.&lt;/p&gt;&#xA;&lt;p&gt;In Haskell, an expression such as &lt;code&gt;add x y = x + y&lt;/code&gt; defines a pure function. It is a function rather than a method because it does not belong to a class or an object: there is no implicit receiver (this) and no dot-syntax. It is simply a mapping from inputs to an output.&lt;/p&gt;&#xA;&lt;p&gt;The function is pure because it has no side effects and is deterministic: for the same inputs, it always produces the same result. This property allows the expression to be reasoned about mathematically and makes its behaviour predictable and testable.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;“Methods” do exist in Haskell&lt;/strong&gt;, but they’re tied to &lt;em&gt;type classes&lt;/em&gt;, roughly corresponding to Scala typeclasses. That is a different mental model than object-oriented methods. These examples use plain functions:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-haskell&#34; data-lang=&#34;haskell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function doubles its input. No types are written here because languages in the ML family introduced &lt;strong&gt;type inference&lt;/strong&gt;. Robin Milner and others introduced type inference in the 1970s, and the compiler can often infer types automatically. Counterintuitively, the result is concise code without giving up static guarantees.&lt;/p&gt;&#xA;&lt;p&gt;To define types, Haskell uses the &lt;code&gt;::&lt;/code&gt; syntax:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-haskell&#34; data-lang=&#34;haskell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Int&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Repeating the name – once for the type signature and once for the definition – can look “anti-DRY”. In practice, it separates the declaration from the implementation and makes the code easier to reason about. It also keeps the abstract level of types separate from implementation details.&lt;/p&gt;&#xA;&lt;aside class=&#34;not-prose my-6 rounded-md border-l-4 border-slate-200 bg-slate-50 dark:border-slate-600 dark:bg-slate-800 text-slate-800 dark:text-slate-200 px-4 py-3&#34;&gt;&#xA;  &lt;div class=&#34;flex items-start gap-2&#34;&gt;&#xA;    &lt;span class=&#34;mt-[2px] opacity-60 leading-none&#34; aria-hidden=&#34;true&#34;&gt;&#xA;      ℹ️&#xA;    &lt;/span&gt;&#xA;&#xA;    &lt;div class=&#34;space-y-2 text-sm sm:text-base leading-relaxed&#34;&gt;&#xA;      &lt;div class=&#34;flex items-center gap-2 font-semibold&#34;&gt;Haskell Fact 1&lt;/div&gt;&#xA;&#xA;      &lt;div class=&#34;&#xA;        [&amp;&gt;p]:m-0&#xA;        [&amp;&gt;ul]:m-0 [&amp;&gt;ul]:list-disc [&amp;&gt;ul]:pl-5&#xA;        [&amp;&gt;ol]:m-0 [&amp;&gt;ol]:list-decimal [&amp;&gt;ol]:pl-5&#xA;        [&amp;&gt;ul&gt;li]:mt-1 [&amp;&gt;ol&gt;li]:mt-1&#xA;        [&amp;&gt;ul&gt;li::marker]:opacity-50&#xA;        [&amp;&gt;ol&gt;li::marker]:opacity-50&#xA;        [&amp;&gt;pre]:m-0 [&amp;&gt;pre]:overflow-x-auto&#xA;        [&amp;_a]:underline [&amp;_a]:underline-offset-2 [&amp;_a]:font-semibold&#xA;&#34;&gt;&lt;p&gt;Haskell separates:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;what it is&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;from &lt;strong&gt;how it works&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;From a more mathematical point of view:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the &lt;strong&gt;type signature is a theorem&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;the &lt;strong&gt;function body is a proof&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;From a more mathematical point of view, Haskell treats types like a form of logic: the type signature is a theorem, and the function body is a proof.&lt;/p&gt;&#xA;&lt;p&gt;When should type signatures be written, and when should inference be used?&lt;/p&gt;&#xA;&lt;aside class=&#34;not-prose my-6 rounded-md border-l-4 border-slate-200 bg-slate-50 dark:border-slate-600 dark:bg-slate-800 text-slate-800 dark:text-slate-200 px-4 py-3&#34;&gt;&#xA;  &lt;div class=&#34;flex items-start gap-2&#34;&gt;&#xA;    &lt;span class=&#34;mt-[2px] opacity-60 leading-none&#34; aria-hidden=&#34;true&#34;&gt;&#xA;      ✅&#xA;    &lt;/span&gt;&#xA;&#xA;    &lt;div class=&#34;space-y-2 text-sm sm:text-base leading-relaxed&#34;&gt;&#xA;      &lt;div class=&#34;flex items-center gap-2 font-semibold&#34;&gt;Haskell Rule 1&lt;/div&gt;&#xA;&#xA;      &lt;div class=&#34;&#xA;        [&amp;&gt;p]:m-0&#xA;        [&amp;&gt;ul]:m-0 [&amp;&gt;ul]:list-disc [&amp;&gt;ul]:pl-5&#xA;        [&amp;&gt;ol]:m-0 [&amp;&gt;ol]:list-decimal [&amp;&gt;ol]:pl-5&#xA;        [&amp;&gt;ul&gt;li]:mt-1 [&amp;&gt;ol&gt;li]:mt-1&#xA;        [&amp;&gt;ul&gt;li::marker]:opacity-50&#xA;        [&amp;&gt;ol&gt;li::marker]:opacity-50&#xA;        [&amp;&gt;pre]:m-0 [&amp;&gt;pre]:overflow-x-auto&#xA;        [&amp;_a]:underline [&amp;_a]:underline-offset-2 [&amp;_a]:font-semibold&#xA;&#34;&gt;&lt;p&gt;Top-level definitions should have explicit type signatures.&lt;/p&gt;&#xA;&lt;p&gt;Add types:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if it is a top-level function that will be public in the module&lt;/li&gt;&#xA;&lt;li&gt;if a function is complex, and adding types makes it easier to reason&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Skip types:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;simple helper functions which are called by other main ones&lt;/li&gt;&#xA;&lt;li&gt;for simple helpers, let VS Code generate them via quick fix&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;While learning, types are often omitted initially and generated by the editor. Inferred types can be more general, and more complex, than expected because polymorphism introduces &lt;em&gt;typeclass constraints&lt;/em&gt;. A typeclass constraint is a requirement that a type supports a particular set of operations, such as ordering for sorting.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;expressiveness-as-structure&#34;&gt;Expressiveness as structure&lt;/h3&gt;&#xA;&#xA;&lt;h4 id=&#34;decomposition-with-patterns-and-recursion&#34;&gt;Decomposition with patterns and recursion&lt;/h4&gt;&#xA;&lt;p&gt;Pattern matching is a central readability feature. It is used directly in a function definition and is more capable than in many mainstream languages.&lt;/p&gt;&#xA;&lt;p&gt;For example, here is a function that sums a list:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-haskell&#34; data-lang=&#34;haskell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mySum&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mySum&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mySum&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ns&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This definition begins with the base case. When the list is empty, it returns 0.&lt;/p&gt;&#xA;&lt;p&gt;The second clause handles the general case. &lt;strong&gt;Pattern matching&lt;/strong&gt; splits the input into one element &lt;code&gt;n&lt;/code&gt; and the rest of the list &lt;code&gt;ns&lt;/code&gt;, which can still be empty.&lt;/p&gt;&#xA;&lt;p&gt;Function calls don’t require parentheses; the typical form is &lt;code&gt;nameOfFunction arg1 arg2 ...&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In this example, &lt;code&gt;mySum&lt;/code&gt; calls itself – classic &lt;strong&gt;recursion&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;A common question is whether this is stack-safe and performant. In general, the naive version is &lt;em&gt;not&lt;/em&gt; stack-safe. However, idiomatic Haskell uses a strict fold like &lt;code&gt;foldl&#39;&lt;/code&gt;, or an explicit accumulator, to avoid building up thunks, or deferred computations. For summing there are built-in helpers already.&lt;/p&gt;&#xA;&lt;p&gt;A rough progression from teaching examples to production code:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;recursion replaces loops&lt;/li&gt;&#xA;&lt;li&gt;but folds replace recursion&lt;/li&gt;&#xA;&lt;li&gt;and strict folds replace naive folds&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4 id=&#34;declarative-formulations&#34;&gt;Declarative formulations&lt;/h4&gt;&#xA;&lt;p&gt;Declarative style supports reasoning: it describes &lt;em&gt;what&lt;/em&gt; is needed, not &lt;em&gt;how&lt;/em&gt; to do it step-by-step.&lt;/p&gt;&#xA;&lt;p&gt;Quicksort illustrates the declarative style:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-haskell&#34; data-lang=&#34;haskell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;qsort&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Ord&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;-- (1)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;qsort&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;-- (2)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;qsort&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;qsort&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;smaller&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;++&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;++&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;qsort&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;larger&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;-- (3)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;where&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;-- (4)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;smaller&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;larger&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#xA;&lt;li&gt;Read the type declaration backwards&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;[a]&lt;/code&gt; - list of elements of type a - a is any type like Int, String, or custom types like Person, and the list contains those values, for example a list of ints&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;[a] -&amp;gt; [a]&lt;/code&gt; - the function expects a list of &lt;code&gt;a&lt;/code&gt; and returns a list of &lt;code&gt;a&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;(Ord a) =&amp;gt;&lt;/code&gt; - we accept any type &lt;code&gt;a&lt;/code&gt;, as long as it has an &lt;code&gt;Ord&lt;/code&gt; instance so we can compare/order values of that type&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;It defines sorting for an empty list (the trivial case)&lt;/li&gt;&#xA;&lt;li&gt;It uses pattern matching to split the list into one element x and the rest (xs)&#xA;&lt;ul&gt;&#xA;&lt;li&gt;This is the part where the algorithm looks like a standard quicksort definition.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Recursion&lt;/strong&gt; sorts the &lt;code&gt;smaller&lt;/code&gt; part, concatenates it with the one-element list &lt;code&gt;[x]&lt;/code&gt;, and then concatenates the sorted &lt;code&gt;larger&lt;/code&gt; part&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;where&lt;/code&gt; defines what is meant by &lt;code&gt;smaller&lt;/code&gt; and &lt;code&gt;larger&lt;/code&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We use &lt;code&gt;[a | a &amp;lt;- xs, a &amp;lt;= x]&lt;/code&gt;, a list comprehension that looks like mathematical set-builder notation. That’s one reason mathematicians often enjoy Haskell.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Is this faster than C++/Java? Typically not.&lt;/p&gt;&#xA;&lt;p&gt;It is mainly an example of expressive syntax. However, performance-critical operations typically rely on more specialized structures and primitives. Under the hood, &lt;code&gt;[a]&lt;/code&gt; is a linked list, and append is (O(n)), which makes this particular quicksort formulation expensive.&lt;/p&gt;&#xA;&lt;p&gt;Is it possible to implement a fast quicksort in Haskell? Yes – but it requires addressing the bottleneck and using something more appropriate, like &lt;code&gt;Data.Vector&lt;/code&gt; / &lt;code&gt;Data.Array&lt;/code&gt;, or using a well-tested library implementation.&lt;/p&gt;&#xA;&lt;p&gt;This shows a familiar FP trade-off: purity supports reasoning and the modelling of business rules, yet mission-critical performance often requires controlled mutation.&lt;/p&gt;&#xA;&lt;aside class=&#34;not-prose my-6 rounded-md border-l-4 border-slate-200 bg-slate-50 dark:border-slate-600 dark:bg-slate-800 text-slate-800 dark:text-slate-200 px-4 py-3&#34;&gt;&#xA;  &lt;div class=&#34;flex items-start gap-2&#34;&gt;&#xA;    &lt;span class=&#34;mt-[2px] opacity-60 leading-none&#34; aria-hidden=&#34;true&#34;&gt;&#xA;      ℹ️&#xA;    &lt;/span&gt;&#xA;&#xA;    &lt;div class=&#34;space-y-2 text-sm sm:text-base leading-relaxed&#34;&gt;&#xA;      &lt;div class=&#34;flex items-center gap-2 font-semibold&#34;&gt;Haskell Fact 2&lt;/div&gt;&#xA;&#xA;      &lt;div class=&#34;&#xA;        [&amp;&gt;p]:m-0&#xA;        [&amp;&gt;ul]:m-0 [&amp;&gt;ul]:list-disc [&amp;&gt;ul]:pl-5&#xA;        [&amp;&gt;ol]:m-0 [&amp;&gt;ol]:list-decimal [&amp;&gt;ol]:pl-5&#xA;        [&amp;&gt;ul&gt;li]:mt-1 [&amp;&gt;ol&gt;li]:mt-1&#xA;        [&amp;&gt;ul&gt;li::marker]:opacity-50&#xA;        [&amp;&gt;ol&gt;li::marker]:opacity-50&#xA;        [&amp;&gt;pre]:m-0 [&amp;&gt;pre]:overflow-x-auto&#xA;        [&amp;_a]:underline [&amp;_a]:underline-offset-2 [&amp;_a]:font-semibold&#xA;&#34;&gt;Purity outside, mutation inside:&lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;This separation is generally less direct in Java/C++ when separating mutation from interface.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;sequencing-effects-with-monads&#34;&gt;Sequencing effects with monads&lt;/h4&gt;&#xA;&lt;p&gt;The next topic is sequencing actions that may involve side effects, such as reading characters from input.&lt;/p&gt;&#xA;&lt;p&gt;Instead of hard-coding a specific effect type, this is written generically. The &lt;code&gt;Monad&lt;/code&gt; typeclass provides a way to sequence computations within a context &lt;code&gt;m&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The type is:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-haskell&#34; data-lang=&#34;haskell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;seqn&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Monad&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For example: &lt;code&gt;seqn [getChar, getChar, getChar]&lt;/code&gt;, where &lt;code&gt;getChar&lt;/code&gt; is a standard function that reads a character from standard input in Haskell.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;code&gt;do&lt;/code&gt; notation provides syntactic sugar for sequencing monadic operations, combined here with pattern matching and a base case:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-haskell&#34; data-lang=&#34;haskell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;seqn&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Monad&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;seqn&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;-- (1)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;seqn&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;act&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;-- (2)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;act&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;xs&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seqn&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acts&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;-- (3)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are a couple of new elements here:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;-&lt;/code&gt; is called &lt;strong&gt;monadic bind&lt;/strong&gt; operation. It runs the monadic action &lt;code&gt;act&lt;/code&gt;, extracts its result, and binds it to &lt;code&gt;x&lt;/code&gt; while staying in the context of the monad, for example the console input context.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;do&lt;/code&gt; provides a common way to write a sequence of monadic operations. First &lt;code&gt;act&lt;/code&gt; is run, for example &lt;code&gt;getChar&lt;/code&gt;, and its result is bound to &lt;code&gt;x&lt;/code&gt;. Then the same function is called on the remaining actions. Finally, &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;xs&lt;/code&gt; are combined, and &lt;code&gt;return&lt;/code&gt; is used to produce &lt;code&gt;m [a]&lt;/code&gt;; without &lt;code&gt;return&lt;/code&gt;, the result would be &lt;code&gt;[a]&lt;/code&gt;, which would not match the type signature.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&lt;p&gt;This is the first part of a longer series.&lt;/p&gt;&#xA;&lt;p&gt;This section covered setting up a Haskell project in VS Code.&lt;/p&gt;&#xA;&lt;p&gt;It implemented several examples with types and functions, and demonstrated how expressive Haskell is with pattern matching and declarative syntax.&lt;/p&gt;&#xA;&lt;p&gt;It also provided an initial example of monads and &lt;code&gt;do&lt;/code&gt; notation.&lt;/p&gt;&#xA;&lt;p&gt;Overall, this illustrates how Haskell’s type-driven style supports reasoning about program structure and behavior even in early, small examples.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;Programming in Haskell&lt;/em&gt; – Graham Hutton&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
    </item>
  </channel>
</rss>
