<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>straszydlo</title>
    <description>Making you scared with bad code
</description>
    <link>straszydlo.github.io/</link>
    <atom:link href="straszydlo.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 20 Aug 2025 20:53:01 +0000</pubDate>
    <lastBuildDate>Wed, 20 Aug 2025 20:53:01 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Freedom fuel</title>
        <description>&lt;h3 id=&quot;in-a-nutshell&quot;&gt;In a nutshell&lt;/h3&gt;
&lt;p&gt;I just finished watching a wonderful episode of Kurzgesagt&lt;sup id=&quot;fnref:video&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:video&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; about alcohol and our relationship with it. Despite starting with calling alcohol “the most harmful substance on Earth”, the video could serve as an ad for ethanol consumption — it explains in great detail why it makes us feel great, and it even suggests that alcohol helped societies thrive by helping overcome anxiety and break down social barriers.&lt;/p&gt;

&lt;p&gt;While that claim might not be true, this “pact with the devil”, as Kurzgesagt calls it, might actually have had a much more &lt;em&gt;technical&lt;/em&gt; benefit for early societies. Ethanol is quite effective as a crude food preservative — and what’s even better, alcohol fermentation pretty much happens on its own. It was an invaluable tool for our earliest ancestors, who oftentimes had to endure long periods without access to fresh fruits or grains. I’m far from advocating &lt;strong&gt;for&lt;/strong&gt; ingesting alcohol, as nowadays we have healthier and more effective ways of stopping our fruits from going bad — but it might not be worth pouring it all down the drain. We may have not yet seen the good old &lt;em&gt;aqua vitae&lt;/em&gt;’s full potential.&lt;/p&gt;

&lt;h3 id=&quot;what-makes-my-engine-tick&quot;&gt;What makes my engine tick&lt;/h3&gt;
&lt;p&gt;Biofuels are nothing new. Historically cars used to run on all kinds of combustible liquids. In fact pure ethanol powered Henry Ford’s first car, the Quadricycle — it only fell out of favor during the Prohibition due to gasoline being cheaper&lt;sup id=&quot;fnref:gasoline&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:gasoline&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. Contemporary gasoline all over the world usually contains at least some ethanol. Brazil went even further — all new vehicles sold there are flexfuel-capable, meaning they can run on a blend of gasoline and ethanol in pretty much any proportion. It makes sense — it lets Brazil shield itself from oil shortages and cut CO₂ emissions. In fact ethanol is superior to gasoline in many regards: it is more resistant to knock, allowing running higher compression ratios for higher efficiency and more torque; its air-fuel ratio is better, allowing extracting more power from a given cylinder volume; it burns cleaner and has much lower carbon footprint&lt;sup id=&quot;fnref:ecology&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ecology&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;; it makes the engine run cooler&lt;sup id=&quot;fnref:cool&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:cool&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;; and finally it’s fully renewable. The only issue is its energy density, which is around 67% of gasoline, meaning the engine has to burn more fuel to produce the same power. It’s a no-brainer&lt;sup id=&quot;fnref:caveat&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:caveat&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. Since ethanol is much cheaper to produce now than gasoline&lt;sup id=&quot;fnref:source&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:source&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, it seems like the only thing stopping us from switching over is the fact that we got used to the status quo.&lt;/p&gt;

&lt;h3 id=&quot;what-fuels-the-cells&quot;&gt;What fuels the cells&lt;/h3&gt;
&lt;p&gt;Combustion, however cozy and heartwarming, is not the only way of extracting energy back out of alcohol (or rather alcohols in general). Fuel cells can convert alcohol into electricity — either directly&lt;sup id=&quot;fnref:DEFC&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:DEFC&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; or indirectly — and do it easily and efficiently. They may not outperform hydrogen fuel cells, but since hydrogen is notoriously difficult to store, the lower cost of infrastructure for liquid fuels is a huge advantage. Even more importantly, it is possible to produce alcohols electrochemically — and that method is currently being intensively researched&lt;sup id=&quot;fnref:electrochemical&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:electrochemical&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;. If it proves to be effective, it will open another possibility of storing energy from renewable sources, further smoothing out the fluctuations in available power.&lt;/p&gt;

&lt;h3 id=&quot;fuel-for-freedom&quot;&gt;Fuel for freedom&lt;/h3&gt;
&lt;p&gt;The most unexpected benefit comes from the low-tech nature of ethanol. It is always available — you just need to mix water and something that contains sugar, let the wild yeast ferment the mash, and then distill the mash using something as simple as a clay retort placed in the middle of a bonfire. Compared to the complexity of refining crude oil, this is trivial — anyone can do it anywhere. This means that in the event of a zombie apocalypse Brazil will have the highest number of cars still on the road, but it also means that individuals can still make their own fuel in case of an oil shortage, war or global economic collapse. It is impossible to ban, and no corporation can control the whole supply chain tightly enough to force everyone to buy their product. Moreover, the advances in the fuel cell technology and electrochemical synthesis it might actually allow people to efficiently make ethanol with just as much as a single solar panel. That’s as close to self-sufficiency as it gets!&lt;/p&gt;

&lt;p&gt;Quite ironically, the same substance that harms so many and has been used by oppressors to control the oppressed&lt;sup id=&quot;fnref:Russia&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:Russia&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;, might actually pave the way to a greener, more decentralized and more free future. Here’s to a brighter tomorrow!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:video&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://youtu.be/aOwmt39L2IQ&quot;&gt;Alcohol is AMAZING, Kurzgesagt - In a Nutshell&lt;/a&gt; &lt;a href=&quot;#fnref:video&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:gasoline&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Ethanol_fuel_in_the_United_States#cite_ref-Ethanol_25-0&quot;&gt;Thus says Wikipedia.&lt;/a&gt; &lt;a href=&quot;#fnref:gasoline&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ecology&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://ethanolrfa.org/media-and-news/category/blog/article/2022/10/the-truth-about-ethanol-and-carbon-emissions&quot;&gt;The Truth About Ethanol and Carbon Emissions, Renewable Fuels Association&lt;/a&gt; &lt;a href=&quot;#fnref:ecology&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:cool&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://grassrootsmotorsports.com/articles/why-does-e85-run-cooler-and-make-more-power/&quot;&gt;Cool.&lt;/a&gt; &lt;a href=&quot;#fnref:cool&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:caveat&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Some people claim that ethanol has a tendency to destroy engines. This is mostly untrue, with the exception of rubber tubing on old cars that tends to crumble after prolonged contact with ethanol. Fortunately it’s easy to fix - just replace it. All the hoses are now manufactured with ethanol content in mind. The other claim that ethanol has a corrosive effect on aluminium due to accumulation of water is questionable at best. Aluminium passivates itself quickly in contact with air, and the resulting aluminium oxide does not react with either water or ethanol under normal conditions. &lt;a href=&quot;#fnref:caveat&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:source&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://docs.nrel.gov/docs/fy01osti/28893.pdf&quot;&gt;Cost of production of one gallon of ethanol, estimated to $0.90&lt;/a&gt; vs &lt;a href=&quot;https://www.api.org/oil-and-natural-gas/energy-primers/gas-prices-explained&quot;&gt;cost of production of one gallon of gasoline, estimated to $2.70&lt;/a&gt;. &lt;a href=&quot;#fnref:source&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:DEFC&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Direct-ethanol and direct-methanol fuel cells are relatively simple to build and promise a 97% theoretical efficiency. Improving actual efficiency is a subject of research. &lt;a href=&quot;#fnref:DEFC&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:electrochemical&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Papers on synthesis of &lt;a href=&quot;https://doi.org/10.1016/j.nanoen.2024.110099&quot;&gt;methanol&lt;/a&gt; and &lt;a href=&quot;https://doi.org/10.1021/acsenergylett.0c02610&quot;&gt;ethanol&lt;/a&gt;. &lt;a href=&quot;#fnref:electrochemical&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:Russia&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://allthatsinteresting.com/vodka-russia-history&quot;&gt;Russia is the prime example&lt;/a&gt;, but similar measures were implemented on Polish lands occupied by tsarist Russia after Partitions of Poland. Also the now-outlawed practice of paying workers with alcohol instead of money in South Africa is considered by many to have been a form of deliberate oppression. &lt;a href=&quot;#fnref:Russia&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 20 Aug 2025 00:00:00 +0000</pubDate>
        <link>straszydlo.github.io/technology/sustainability/renewable%20resources/rant/2025/08/20/freedom_fuel.html</link>
        <guid isPermaLink="true">straszydlo.github.io/technology/sustainability/renewable%20resources/rant/2025/08/20/freedom_fuel.html</guid>
        
        
        <category>Technology</category>
        
        <category>Sustainability</category>
        
        <category>Renewable Resources</category>
        
        <category>Rant</category>
        
      </item>
    
      <item>
        <title>Turning type-level magic into money</title>
        <description>&lt;h3 id=&quot;money-money-money&quot;&gt;Money, money, money&lt;/h3&gt;
&lt;p&gt;Every single one of us handles money-related code at some point in time — be it because of the particular domain we work on, our own convenience, or just as a mental exercise. Regardless of the motivation, we all learn sooner or later that this is a surprisingly non-trivial topic, especially that it’s critically important to do everything right.&lt;/p&gt;

&lt;h3 id=&quot;weve-all-been-there&quot;&gt;We’ve all been there&lt;/h3&gt;
&lt;p&gt;Let’s say we have some cash in different currencies, and wish to know how much dollars these amount to. A naive model could look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;@main def run =
  val pounds: BigDecimal = 2.0
  val exchange: BigDecimal = 1.2 //Bad naming!
  val dollars = pounds * exchange
  val savingsDollars: BigDecimal = 3.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We all know how it ends:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;  val dollarsInCash = dollars + savingsDollars
  val dollarsInCashAndFromExchange = dollars + savingsDollars + exchange //Horribly wrong!
  println(s&quot;Dollars from selling pounds: $dollars, from savings: $savingsDollars. Total: $dollarsInCash&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A mistake that could be fixed with better naming, one could argue — the problem however is that this bug is especially hard to spot, and nothing helps us to do so!&lt;/p&gt;

&lt;h3 id=&quot;enter-the-model&quot;&gt;Enter the Model&lt;/h3&gt;
&lt;p&gt;Let’s address that issue, and give our values a proper representation:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Money(value: BigDecimal)
case class Rate(rate: BigDecimal)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now confusing an exchange rate with money should not be possible, at least on the surface. Let’s look at the usage:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;@main def run =
  val pounds: Money = Money(2.0)
  val poundsToDollars = Rate(1.2)
  val dollars = pounds.value + poundsToDollars.rate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turns out wrapping values in domain classes enforces nothing if the first thing we have to do in order to perform any sensible operation is to unwrap the values manually. The next step is to enrich the model with combinators:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Money private(value: BigDecimal):
  def +(other: Money): Money = Money(value + other.value)
  def exchange(rate: Rate): Money = Money(value * rate.rate)
  override def toString = value.toString
case class Rate(rate: BigDecimal)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we are safe.&lt;/p&gt;

&lt;p&gt;Or are we?&lt;/p&gt;
&lt;h3 id=&quot;foiled-again&quot;&gt;Foiled again&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;@main def run =
  val pounds: Money = Money(2.0)
  val poundsToDollars = Rate(1.2)
  val dollars = pounds.exchange(poundsToDollars)
  val dollarsInCash = pounds + dollars
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our model misses some crucial information — there are several different currencies that cannot be added, at least not without converting them first. Modeling this information is straightforward:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Currency(name: String):
  override def toString = name
case class Money(value: BigDecimal, currency: Currency):
  def +(other: Money): Money =
    if currency == other.currency
    then Money(value + other.value, currency)
    else throw IllegalArgumentException(s&quot;Mismatched currencies: $currency and ${other.currency}&quot;)
  def exchange(rate: Rate): Money =
    if currency == rate.from
    then Money(value * rate.rate, rate.to)
    else throw IllegalArgumentException(s&quot;Mismatched currencies: $currency and ${rate.from}&quot;)
case class Rate(rate: BigDecimal, from: Currency, to: Currency)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, should anyone try to add mismatching currencies or convert money using a wrong rate, a nasty exception would be thrown in their faces.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;@main def run =
  val gbp = Currency(&quot;GBP&quot;)
  val usd = Currency(&quot;USD&quot;)
  val pounds = Money(2.0, gbp)
  val poundsToDollars = Rate(1.2, gbp, usd)
  val dollars = pounds.exchange(poundsToDollars)

  //These two blow up!
  val totalCash = pounds + dollars
  val dollarsToPounds = dollars.exchange(poundsToDollars)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;all-is-good&quot;&gt;All is good&lt;/h3&gt;
&lt;p&gt;As we can see, a relatively simple model of the domain can make our lives so much simpler, saving us from wasting hours (if not days) of debugging to find a simplest mistake possible.&lt;/p&gt;

&lt;p&gt;As a final touch, let’s get rid of the exceptions in favor of a more sensible error handling mechanism:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Currency(name: String):
  override def toString = name
case class Money(value: BigDecimal, currency: Currency):
  def +(other: Money): Either[MismatchedCurrencies, Money] =
    if currency == other.currency
    then Right(Money(value + other.value, currency))
    else Left(MismatchedCurrencies(currency, other.currency))
  def exchange(rate: Rate): Either[MismatchedCurrencies, Money] =
    if currency == rate.from
    then Right(Money(value * rate.rate, rate.to))
    else Left(MismatchedCurrencies(currency, rate.from))
case class Rate(rate: BigDecimal, from: Currency, to: Currency)
case class MismatchedCurrencies(c1: Currency, c2: Currency)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;or-is-it&quot;&gt;…or is it?&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;def calculateUSIncomeTax(dollars: Money): Money =
  //Skipping the implementation, as taxes are ridiculously complicated
  ???

@main def run =
  val gbp = Currency(&quot;GBP&quot;)
  val usd = Currency(&quot;USD&quot;)
  val pounds = Money(2.0, gbp)
  val tax = calculateUSIncomeTax(pounds)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is nothing we can do to prevent passing a wrong currency into a wrong place. Even worse, if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;calculateUSIncomeTax&lt;/code&gt; implementor did not place a check inside, we would have no clue what went wrong. The nightly debugging session we worked so hard to prevent seems inevitable.&lt;/p&gt;

&lt;p&gt;In addition, switching from exceptions to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt; made our API a bit less convenient — now we have to use pattern matching or for-comprehensions everywhere, and cannot chain our operations as nicely as previously:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;@main def run =
  val gbp = Currency(&quot;GBP&quot;)
  for
    pounds &amp;lt;- Money(10, gpb) + Money(11, gbp)
    morePounds &amp;lt;- pounds + Money(0.37, gbp) //We cannot do `Money(10, gbp) + Money(11, gbp) + Money(0.37, gbp)` anymore!
  yield morePounds
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Can we somehow make the implementation safer? Or at least get the nice API back?&lt;/p&gt;

&lt;h3 id=&quot;phantom-menace&quot;&gt;Phantom menace&lt;/h3&gt;
&lt;p&gt;The answer is yes — if you wish to sell your soul to the type-level devil and let the compiler check the validity of your operations. First let’s lift the currency information into the type level:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;sealed trait Currency
sealed trait GBP extends Currency
sealed trait USD extends Currency
sealed trait CHF extends Currency
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then let’s add some type parameters to our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Money&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rate&lt;/code&gt; classes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Money[A](value: BigDecimal):
  def +(other: Money[A]): Money[A]
  def exchange[B](rate: Rate[A, B]): Money[B] =
    Money(value * rate.rate)
case class Rate[A, B](rate: BigDecimal)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These type parameters don’t serve any purpose except distinguishing between different currencies, and don’t interact in any way with the “value” world — - therefore we call them “phantom type parameters”.
Now we can observe that invalid additions and conversions are no longer possible:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;@main def run =
  val pounds = Money[GBP](2.0)
  val dollars = Money[USD](3.0)
  //pounds + dollars //Does not compile!
  val poundsToDollars = Rate[GBP, USD](1.2)
  val total = pounds.exchange(poundsToDollars) + dollars
  //dollars.exchange(poundsToDollars) //Does not compile!
  //val money: Money[GBP] = Money[CHF](2.0) //Does not compile!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We both have prevented invalid behavior at compile time &lt;strong&gt;and&lt;/strong&gt; regained our nice API!&lt;/p&gt;

&lt;h3 id=&quot;the-price&quot;&gt;The price&lt;/h3&gt;
&lt;p&gt;We have, however, lost a couple of things. First, we cannot display our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Money&lt;/code&gt; objects nicely anymore, since the currency info is no longer just a value, but instead a type parameter that ceases to exist at runtime; second, the implementation became less elegant, as now we have a dedicated trait hierarchy just for marking our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Money&lt;/code&gt; while most likely still needing the value-level representation for different use cases. The former is an easily fixable detail, the latter is a sacrifice we might be willing to make when safety is critical.&lt;/p&gt;

&lt;h3 id=&quot;singleton-of-scalatown&quot;&gt;Singleton of Scalatown&lt;/h3&gt;
&lt;p&gt;There is one more thing that we can do, a trick that relies on an obscure, borderline black magic Scala feature. If you are satisfied with the solution above, feel free to skip the rest — otherwise fasten your seatbelts and abandon all hope.&lt;/p&gt;

&lt;p&gt;Enter the singleton types.&lt;/p&gt;

&lt;p&gt;When we think about types, our intuition tends to revolve around sets of values that share some common traits, constraints or behaviors. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;s are plain integers from a certain range, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;s are sequences of characters, various object types are whatever we want them to be. Some of these sets of values are subsets of other, broader sets — establishing a relationship we call “subtyping”. This intuition does not prevent us from constructing types inhabited by a single value (or none, for what it’s worth); so when we reverse our thinking, every single value gives rise to a distinct type - a type that we might interpret as a restriction “values of this type are only this single, specific thing”. Scala 2.13 introduced this notion to its type system&lt;sup id=&quot;fnref:SIP-23&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:SIP-23&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, allowing for constructs like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;val thisIs213: &quot;213&quot; = &quot;213&quot;
def doSomethingWith213(argument: &quot;213&quot;): String =
  s&quot;$argument is 213, as it cannot be anything else&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thanks to this we can impose restrictions of power previously unknown, and we can refine our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Money&lt;/code&gt; model even further:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Currency(name: String):
  override def toString = name
case class Money[A](value: BigDecimal, currency: A):
  def +(other: Money[A]) = Money(value + other.value, currency)
  def exchange[B](rate: Rate[A, B]): Money[B] =
    Money(value * rate.rate, rate.to)
  override def toString = s&quot;$value $currency&quot;
case class Rate[A, B](rate: BigDecimal, from: A, to: B)

@main def run =
  val gbp = Currency(&quot;GBP&quot;)
  val usd = Currency(&quot;USD&quot;)
  val pounds = Money[gbp.type](2.0, gbp)
  val poundsToDollars = Rate[gbp.type, usd.type](1.2, gbp, usd)
  val dollars: Money[usd.type] = pounds.exchange(poundsToDollars)
  //println(pounds + dollars) //Does not compile!
  //println(dollars.exchange(poundsToDollars)) //Does not compile!
  //val dollarsAgain: Money[usd.type] = pounds //Does not compile!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can now freely add new currencies as we go, we have retained our nice API&lt;sup id=&quot;fnref:tradeoff&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tradeoff&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, and we are as safe as it gets!&lt;/p&gt;

&lt;h3 id=&quot;whats-the-value-of-a-singleton-type&quot;&gt;What’s the value of a singleton type?&lt;/h3&gt;
&lt;p&gt;The example above has the downside of unnecessary constructor parameters. We’d like to get rid of them, but that would mean our overloaded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toString&lt;/code&gt; wouldn’t work again. Fortunately, retrieving a value of a singleton type should be quite simple — and indeed, Scala provides us with a nice way of doing exactly that. With the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValueOf&lt;/code&gt; context bound we can rewrite our code into its final form (taking the liberty to organize stuff a bit):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;//Here&apos;s our model:
case class Currency(name: String):
  override def toString = name

case class Money[A: ValueOf](value: BigDecimal):
  def +(other: Money[A]) = Money(value + other.value)
  def exchange[B: ValueOf](rate: Rate[A, B]): Money[B] =
    Money(value * rate.rate)
  def exchangeFor[B: ValueOf](using rate: Rate[A, B]): Money[B] =
    exchange(rate)
  //The `ValueOf` context bound effectively marks our type as a singleton type.
  //By its virtue we get the `valueOf` method, which allows summoning the value of our singleton type.
  override def toString = s&quot;$value ${valueOf[A]}&quot;

case class Rate[A, B](rate: BigDecimal):
  def andThen[C](other: Rate[B, C]): Rate[A, C] =
    Rate(rate * other.rate)

//We can define our custom apply for convenience:
object Money:
  def apply(value: BigDecimal, currency: Currency): Money[currency.type] =
    Money(value)

//And some example values:
object Currencies:
  val gbp = Currency(&quot;GBP&quot;)
  type GBP = gbp.type
  val usd = Currency(&quot;USD&quot;)
  type USD = usd.type
  val chf = Currency(&quot;CHF&quot;)
  type CHF = chf.type

object Rates:
  import Currencies.*
  given Rate[GBP, USD] = Rate(1.2)
  given Rate[USD, CHF] = Rate(0.9)
  given transitiveRate[A: ValueOf, B, C: ValueOf](using r1: Rate[A, B], r2: Rate[B,C]): Rate[A, C] =
    r1.andThen(r2)

@main def run =
  import Currencies.*
  import Rates.given
  val pounds: Money[GBP] = Money(2.0)
  val alsoPounds = Money(2.0, gbp) //using the convenience apply method
  val dollars = pounds.exchangeFor[USD]
  val francs = pounds.exchangeFor[CHF]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this technique we have forced the compiler to check the correctness of our domain logic — the benefits are hard to overstress. And all that thanks to a simple concept!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:SIP-23&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/42.type.html&quot;&gt;A detailed description of the feature&lt;/a&gt; &lt;a href=&quot;#fnref:SIP-23&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tradeoff&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;There is a limitation to this — singleton types rely on the notion of a stable path, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Currency(&quot;EUR&quot;).type&lt;/code&gt; unfortunately is not a valid singleton. It also means that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val eur1 = Currency(&quot;EUR&quot;)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val eur2 = Currency(&quot;EUR&quot;)&lt;/code&gt; give rise to two different singleton types. &lt;a href=&quot;#fnref:tradeoff&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 22 May 2023 00:00:00 +0000</pubDate>
        <link>straszydlo.github.io/scala%203/type-level%20magic/functional%20programming/2023/05/22/turning_type_level_magic_into_money.html</link>
        <guid isPermaLink="true">straszydlo.github.io/scala%203/type-level%20magic/functional%20programming/2023/05/22/turning_type_level_magic_into_money.html</guid>
        
        
        <category>Scala 3</category>
        
        <category>Type-level magic</category>
        
        <category>Functional programming</category>
        
      </item>
    
      <item>
        <title>A primer on Readers</title>
        <description>&lt;h3 id=&quot;the-dream&quot;&gt;The dream&lt;/h3&gt;
&lt;p&gt;Imagine we have functions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;def f: A =&amp;gt; B = ???
def g: B =&amp;gt; C = ???
def h: C =&amp;gt; D = ???
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation may be whatever we want it to be, these functions might parse some data, perform calculations, format strings et cetera. Now, often we want to chain multiple operations together — ie. parse a JSON with sales data, then extract monthly sales figures and finally output an average. After all, coding is all about gluing blocks together to create a useful program.
We could, of course, write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h(g(f(x)))&lt;/code&gt; each time we want the whole functionality, but if it’s used frequently, giving it a proper name is a good idea.
Scala gives us many different ways of gluing functions together, but I’m going to stick to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;andThen&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Function1&lt;/code&gt; trait — because it behaves almost like the mathematical &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;∘&lt;/code&gt; operator, just in reverse order&lt;sup id=&quot;fnref:compose&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:compose&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. With it creating a function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i: A =&amp;gt; D&lt;/code&gt; is as simple as writing:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;def i: A =&amp;gt; D = f andThen g andThen h
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;the-reality&quot;&gt;The reality&lt;/h3&gt;
&lt;p&gt;This kind of composition, obviously, works only for functions with one argument — with multi-argument functions we quickly run into a world of trouble. Quite unfortunate, since the vast majority of those we encounter on a daily basis need more than one input. But what if all of our functions look like this?:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;def f: E =&amp;gt; A =&amp;gt; B = ???
def g: E =&amp;gt; B =&amp;gt; C = ???
def h: E =&amp;gt; C =&amp;gt; D = ???
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is again a common thing — oftentimes we need to pass some sort of a context (or other dependency) to our methods. It would be useful to be able to compose them, even if just to save us some writing.
They share the type of the first argument — it must have made our task easier. What do we need to do to be able to compose them in a sensible way?&lt;/p&gt;

&lt;h2 id=&quot;the-promise&quot;&gt;The promise&lt;/h2&gt;
&lt;p&gt;First of all, let’s simplify things a bit and imagine a function that magically reads some value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;V&lt;/code&gt; from an environment &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E&lt;/code&gt;. It’s going to have a type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E =&amp;gt; V&lt;/code&gt;. We’re going to call it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader&lt;/code&gt; for precisely that reason, and we’re going to wrap it in a case class for convenience:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Reader[E, V](read: E =&amp;gt; V)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We’re halfway there, we just need to notice that function parameters should be swappable (with possible minor tweaks to the logic inside — but usually we don’t depend on their order anyway). Then we can rewrite our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h&lt;/code&gt; as:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;def f: A =&amp;gt; E =&amp;gt; B = ???
def g: B =&amp;gt; E =&amp;gt; C = ???
def h: C =&amp;gt; E =&amp;gt; D = ???
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There’s a lot of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader&lt;/code&gt;s just waiting in line. We can now rewrite our functions again:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;def f: A =&amp;gt; Reader[E, B] = ???
def g: B =&amp;gt; Reader[E, C] = ???
def h: C =&amp;gt; Reader[E, D] = ???
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;the-solution&quot;&gt;The solution&lt;/h3&gt;
&lt;p&gt;Now we just need to compose these somehow. First of all, let’s give our Reader a helper method:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Reader[E, V](read: E =&amp;gt; V) {
  def pipeTo[W](other: V =&amp;gt; Reader[E, W]): Reader[E, W] = Reader { env =&amp;gt;
    val result1 = read(env)
    other(result1).read(env)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we can make ourselves a helper:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;object Reader {
  implicit class ReaderOps[E, A, B](f1: A =&amp;gt; Reader[E, B]) {
    def andThenR[C](f2: B =&amp;gt; Reader[E, C]): A =&amp;gt; Reader[E, C] =
      a =&amp;gt; f1(a).pipeTo(f2)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Et voilà, we can now write this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;def i: A =&amp;gt; Reader[E, D] = f andThenR g andThenR h
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it works!&lt;/p&gt;

&lt;h3 id=&quot;a-bit-of-black-magic&quot;&gt;A bit of black magic&lt;/h3&gt;
&lt;p&gt;We can do one more trick. Let’s first refactor the Reader to be able to use Scala’s wonderful for-comprehensions by renaming &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipeTo&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt; and adding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; method&lt;sup id=&quot;fnref:Function1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:Function1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;case class Reader[E, V](read: E =&amp;gt; V) {
  def map[W](f: V =&amp;gt; W): Reader[E, W] = Reader(env =&amp;gt; f(read(env)))
  def flatMap[W](f: V =&amp;gt; Reader[E, W]): Reader[E, W] = Reader { env =&amp;gt;
    val result1 = read(env)
    f(result1).read(env)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and then define:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;def ask[E]: Reader[E, E] = Reader(identity)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can write stuff like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;val readIncrementAndStringify = for {
  intFromEnvironment &amp;lt;- ask[Int]
  incremented = intFromEnvironment + 1
} yield s&quot;$incremented&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This yields a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader[Int, String]&lt;/code&gt; value, which we can run afterwards to retrieve the final &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; when we need it — but the logic itself looks like pulling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;s out of thin air. Beautiful, isn’t it?&lt;/p&gt;

&lt;h2 id=&quot;the-use&quot;&gt;The use&lt;/h2&gt;
&lt;p&gt;One might ask: why does it matter at all? Aside of the obvious, this can serve as a dependency injection mechanism — functional and type safe. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E&lt;/code&gt; we plug into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader&lt;/code&gt; can be whatever we want — a default value for a given type, an input to a whole computation, a validator or a service with various utilities. We can even stuff multiple things into it!&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Scala&quot;&gt;type Env = (UserDeserializer, UserValidator)

def createUser(input: String): Reader[Env, Option[User]] = for {
  (deserializer, validator) &amp;lt;- ask[Env] //assuming we use better-monadic-for plugin. Who doesn&apos;t?
  deserialized = deserializer.deserialize(input)
  isCorrect = validator.validate(deserialized)
} yield if (isCorrect) Some(deserialized) else None
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This idea is quite similar to how ZIO handles dependency injection&lt;sup id=&quot;fnref:ZIO&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ZIO&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, and how it’s often done in the wide functional world. Of course this implementation is quite limited — but its purpose is to give the reader (pun intended) an intuition on how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader&lt;/code&gt;s work.&lt;/p&gt;

&lt;p&gt;So to sum up: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader&lt;/code&gt; is simply a functional programming pattern for composing two-argument functions that share one of its arguments, and it can be used for anything from passing common values around with less clutter to full-blown dependency injection. Go forth and read!&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:compose&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Scala also defines the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compose&lt;/code&gt; method that behaves exactly like mathematical function composition, but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;andThen&lt;/code&gt; is usually easier to follow, as it reflects the exact order of function application. &lt;a href=&quot;#fnref:compose&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:Function1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Now it becomes clearer why we decided to wrap our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E =&amp;gt; V&lt;/code&gt; function instead of relying on plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Function1&lt;/code&gt; — we want to have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt; methods available. &lt;a href=&quot;#fnref:Function1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ZIO&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;ZIO defines the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ZIO[R, E, A]&lt;/code&gt; type, which uses the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;R&lt;/code&gt; type parameter to pass dependencies around in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reader&lt;/code&gt;-esque fashion. For detailed explanation see:&lt;/p&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&quot;https://zio.dev/&quot;&gt;ZIO documentation&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;https://youtu.be/yXcqjQ7Kcwk&quot;&gt;Wonderful talk by Kit Langton&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;https://softwaremill.com/structuring-zio-2-applications/&quot;&gt;Adam Warski’s post on structuring ZIO 2 applications&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;&lt;a href=&quot;#fnref:ZIO&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 27 Aug 2022 00:00:00 +0000</pubDate>
        <link>straszydlo.github.io/scala%202.13/functional%20programming/2022/08/27/what_is_a_reader_and_why_it_matters.html</link>
        <guid isPermaLink="true">straszydlo.github.io/scala%202.13/functional%20programming/2022/08/27/what_is_a_reader_and_why_it_matters.html</guid>
        
        
        <category>Scala 2.13</category>
        
        <category>Functional programming</category>
        
      </item>
    
  </channel>
</rss>
