<?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: Justin Hewlett</title>
    <description>The latest articles on DEV Community by Justin Hewlett (@jhewlett).</description>
    <link>https://dev.to/jhewlett</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%2F284953%2Fe3ab21d2-73a5-4548-a5d6-ea8d8a2e3de8.jpeg</url>
      <title>DEV Community: Justin Hewlett</title>
      <link>https://dev.to/jhewlett</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jhewlett"/>
    <language>en</language>
    <item>
      <title>To Annotate, or Not to Annotate?</title>
      <dc:creator>Justin Hewlett</dc:creator>
      <pubDate>Thu, 10 Dec 2020 13:48:08 +0000</pubDate>
      <link>https://dev.to/jhewlett/to-annotate-or-not-to-annotate-5dc6</link>
      <guid>https://dev.to/jhewlett/to-annotate-or-not-to-annotate-5dc6</guid>
      <description>&lt;p&gt;As a proud member of the ML family, F# has &lt;a href="https://fsharpforfunandprofit.com/posts/type-inference"&gt;excellent type inference&lt;/a&gt;. This is generally a good thing. But as a newcomer to the language, it's often hard to know when you should use or omit type annotations. Some in the community suggest annotating everything, while others recommend to annotate as little as possible!&lt;/p&gt;

&lt;p&gt;I've experimented with a variety of approaches. While there can be implications on the quality of your code&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, for me it was mostly a source of anxiety: "Am I doing it right?" &lt;/p&gt;

&lt;h2&gt;
  
  
  Strategies
&lt;/h2&gt;

&lt;p&gt;Here are some common strategies I've seen or used:&lt;/p&gt;

&lt;h3&gt;
  
  
  Annotate the bare minimum
&lt;/h3&gt;

&lt;p&gt;The usual argument here is that annotations are noisy, and they make it harder to refactor your code (because in addition to updating your code, you need to update the annotations as they become out of date)&lt;sup id="fnref2"&gt;2&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Some also argue that annotations can make your code unnecessarily specific, preventing reuse. (This is because F# will infer your types to be as generic as possible.)&lt;/p&gt;

&lt;p&gt;All of this advice is reasonable if you're writing application code, where it's generally not a big deal if types change implicitly; you can just go update all the call sites and you're done.&lt;/p&gt;

&lt;h3&gt;
  
  
  No wait, annotate everything!
&lt;/h3&gt;

&lt;p&gt;If you're writing a library, however, accidentally changing the signature of a function is a breaking change and is a much bigger deal.&lt;br&gt;
In that context, it can make a lot more sense to annotate everything to pin down your types.&lt;/p&gt;

&lt;p&gt;I could especially see this approach working well for a library that welcomes external contributors. "Annotate everything" is a simple rule to follow, and it also helps with viewing diffs in a context where you don't have your tooling to help show you the inferred types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Annotate...some of the things?
&lt;/h3&gt;

&lt;p&gt;A more nuanced position is to annotate all public, top-level functions, while allowing private functions to be inferred. This makes it easier to refactor your internals. It still manages to keep noise to a minimum, while keeping your public signatures locked in.&lt;/p&gt;

&lt;p&gt;This is a nice middle ground, and could be used for both application code and libraries. Indeed, &lt;a href="https://docs.microsoft.com/en-us/dotnet/fsharp/style-guide/conventions#type-inference-and-generics"&gt;this seems to be the recommendation&lt;/a&gt; in the F# style guide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Consider labeling argument names with explicit types in public APIs and do not rely on type inference for this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Prototype with inference, then lock it in
&lt;/h3&gt;

&lt;p&gt;In this approach, the general idea is that you start coding without any annotations. Then, as your code starts to take shape, you can check the type that was inferred (e.g. via your editor tooling). Assuming you agree, you can then add the annotation explicitly to pin it down.&lt;/p&gt;

&lt;p&gt;This is similar to the argument that dynamic types are better for prototyping, while static types are better for building the real thing. This is a cool variation though because inference means you don't have to give up type safety!&lt;/p&gt;

&lt;h3&gt;
  
  
  Drive it out with types, then delete the annotations
&lt;/h3&gt;

&lt;p&gt;This one is almost the exact opposite of the previous one. With this strategy, you design all your types upfront: records, unions, and even function signatures. Then you implement the function. The types help you make sure the implementation is correct (likely in addition to testing). Finally, after you've implemented it, you may actually decide to &lt;em&gt;remove the type annotations!&lt;/em&gt; Partly a matter of style, and partly a matter of the context you're working in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use tests to lock in your types
&lt;/h3&gt;

&lt;p&gt;Since it's often a good idea to write tests for your public functions anyway, what if you used those tests to pin down your types? In this way, the tests become your first consumers, documenting their signature through usage.&lt;/p&gt;

&lt;p&gt;Admittedly, this strategy is a bit indirect. But I've observed this in my own code as one reason why I don't always feel the need to annotate my public functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The life of an annotation
&lt;/h2&gt;

&lt;p&gt;A common theme throughout all this is that it's easy to add and remove annotations at will. Some annotations are helpful mostly in development (e.g. to pinpoint an error when you get a confusing error message), while some annotations are more permanent. My advice: embrace this dynamic, and don't be afraid to change your mind. Striving for perfect consistency in &lt;em&gt;where&lt;/em&gt; you add annotations, or &lt;em&gt;when&lt;/em&gt; you add them, is futile. Ultimately, you'll need to experiment to find the right approach that fits your context and style! &lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post is part of the &lt;a href="https://sergeytihon.com/2020/10/22/f-advent-calendar-in-english-2020/"&gt;F# Advent Calendar 2020&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;The one place I can recall introducing a bug due to relying on type inference is when used in conjunction with reflection (e.g. JSON deserialization, or a library like Dapper). You should minimize the use of reflection where you can, and use explicit annotations where you can't. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;This is a case where some people argue the opposite: that a lack of annotations makes it &lt;em&gt;harder&lt;/em&gt; to refactor your code. The main argument here is that you'll feel safer refactoring if you know that you're only changing types explicitly as you update the annotations. I believe this is mainly a &lt;em&gt;perception&lt;/em&gt; of safety over actual safety. (Type inference is different than dynamic typing, after all!) The main caveat here is the combination of reflection and type inference as noted above. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>fsharp</category>
      <category>dotnet</category>
      <category>functional</category>
    </item>
    <item>
      <title>Creating a Functional Wrapper in F#</title>
      <dc:creator>Justin Hewlett</dc:creator>
      <pubDate>Mon, 27 Jul 2020 02:53:26 +0000</pubDate>
      <link>https://dev.to/jhewlett/creating-a-functional-wrapper-in-f-5hgp</link>
      <guid>https://dev.to/jhewlett/creating-a-functional-wrapper-in-f-5hgp</guid>
      <description>&lt;p&gt;One of the big selling points of F# is the wealth of .NET libraries available to you, both in the Base Class Library and NuGet.&lt;/p&gt;

&lt;p&gt;Many of these libraries, however, are developed primarily with C# in mind. They can usually be consumed without issue, but I often find it helpful to write a little wrapper around them to provide a more idiomatic, functional interface. (Plus, it never hurts to build a facade around a third-party dependency!)&lt;/p&gt;

&lt;p&gt;Let's walk through how we might build a wrapper around &lt;code&gt;HttpClient&lt;/code&gt; from the &lt;code&gt;Microsoft.Extensions.Http&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;To start off, here's how we could use &lt;code&gt;HttpClient&lt;/code&gt; to make a &lt;code&gt;GET&lt;/code&gt; request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpClient&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nn"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FromSeconds&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

        &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;requestMessage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpRequestMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nn"&gt;HttpMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"https://hacker-news.firebaseio.com/v0/item/8863.json"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;requestMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AwaitTask&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ReadAsStringAsync&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AwaitTask&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RunSynchronously&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't awful, but I think we can do better. It'd be nice to encapsulate some of these details and make the code a bit more declarative.&lt;/p&gt;

&lt;p&gt;Let's start by defining some types for the interface that we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;HttpMethod&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Get&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Delete&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&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="nc"&gt;Method&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;HttpMethod&lt;/span&gt;
    &lt;span class="nc"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;TimeSpan&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;
    &lt;span class="nc"&gt;Headers&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now, we'll just support &lt;code&gt;GET&lt;/code&gt;s and &lt;code&gt;DELETE&lt;/code&gt;s, but it will be easy to add support for other methods as we need to. We'll require the user to specify a &lt;code&gt;Url&lt;/code&gt; and &lt;code&gt;Method&lt;/code&gt;, but &lt;code&gt;Timeout&lt;/code&gt; and &lt;code&gt;Headers&lt;/code&gt; are optional.&lt;/p&gt;

&lt;p&gt;For our response, we can just capture the status code and body for now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;StatusCode&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="nc"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our types, let's think about what our function signature might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;Http&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpClientFactory&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IHttpClientFactory&lt;/span&gt;&lt;span class="p"&gt;)&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="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll take in an instance of &lt;code&gt;IHttpClientFactory&lt;/code&gt; &lt;sup id="fnref1"&gt;1&lt;/sup&gt; and &lt;code&gt;Request&lt;/code&gt;, and return an &lt;code&gt;Async&amp;lt;Response&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's see how ergonomic it would be to use at this point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://hacker-news.firebaseio.com/v0/item/8863.json"&lt;/span&gt;
        &lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Get&lt;/span&gt;
        &lt;span class="nc"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FromSeconds&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;.)&lt;/span&gt;
        &lt;span class="nc"&gt;Headers&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="s2"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&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;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="n"&gt;httpClientFactory&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RunSynchronously&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not too bad. One thing to note is that even if we don't want to provide a &lt;code&gt;Timeout&lt;/code&gt; or &lt;code&gt;Headers&lt;/code&gt;, we still have to set the properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://hacker-news.firebaseio.com/v0/item/8863.json"&lt;/span&gt;
        &lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Get&lt;/span&gt;
        &lt;span class="nc"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;
        &lt;span class="nc"&gt;Headers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create a helper function to make a request with some default values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;Http&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;createRequest&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="k"&gt;method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
            &lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;method&lt;/span&gt;
            &lt;span class="nc"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;
            &lt;span class="nc"&gt;Headers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createRequest&lt;/span&gt; &lt;span class="s2"&gt;"https://hacker-news.firebaseio.com/v0/item/8863.json"&lt;/span&gt; &lt;span class="nc"&gt;Get&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;requestWithTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FromSeconds&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;.)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;requestWithTimeoutAndHeaders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;requestWithTimeout&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Headers&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="s2"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&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;Since records are immutable, we use &lt;code&gt;with&lt;/code&gt; to create a new instance with some additional properties set.&lt;/p&gt;

&lt;p&gt;This is more tedious than just creating the &lt;code&gt;Request&lt;/code&gt; ourselves and setting all the properties. Let's create some more helper functions for adding a timeout and headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AutoOpen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;]&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;withTimeout&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;withHeader&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Headers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;header&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="nc"&gt;Headers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;request&lt;/code&gt; comes in as the last parameter. This is important to enable pipelining:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createRequest&lt;/span&gt; &lt;span class="s2"&gt;"https://hacker-news.firebaseio.com/v0/item/8863.json"&lt;/span&gt; &lt;span class="nc"&gt;Get&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;withTimeout&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FromSeconds&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;.)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;withHeader&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty slick, right? We've created a little domain-specific language (DSL) to describe the different options, and we can pick and choose what we need.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Overloads to DSLs
&lt;/h2&gt;

&lt;p&gt;In C# land, you might use overloads, optional parameters, and mutable properties to capture the different configuration options. If you layer on dot chaining and some well-designed methods, you can create a fluent builder.&lt;/p&gt;

&lt;p&gt;In F#, there's a strong focus on creating DSLs, using features like records, the pipeline operator, discriminated unions&lt;sup id="fnref2"&gt;2&lt;/sup&gt;, and computation expressions&lt;sup id="fnref3"&gt;3&lt;/sup&gt;. We've created a builder here, not too different than something like LINQ, though it uses function pipelines instead of dot chaining.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing 'execute'
&lt;/h2&gt;

&lt;p&gt;Now that we've talked about the interesting bits, we can see what the implementation of our &lt;code&gt;execute&lt;/code&gt; function might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;HttpMethod&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;method&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Get&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;HttpMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Delete&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;HttpMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Delete&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;Http&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpClientFactory&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IHttpClientFactory&lt;/span&gt;&lt;span class="p"&gt;)&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="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpClientFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CreateClient&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt;

            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Timeout&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;requestMessage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpRequestMessage&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="nc"&gt;Method&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;HttpMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&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="nc"&gt;Url&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="nc"&gt;Headers&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt; &lt;span class="n"&gt;requestMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;

            &lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AwaitTask&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ReadAsStringAsync&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AwaitTask&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;StatusCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StatusCode&lt;/span&gt;
                    &lt;span class="nc"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;body&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;Not too much different from our initial example. We did add a &lt;code&gt;HttpMethod.value&lt;/code&gt; function to convert between our representation and &lt;code&gt;System.Net.Http.HttpMethod&lt;/code&gt;, and we optionally set the timeout via &lt;code&gt;Option.iter&lt;/code&gt; which only runs the callback if we have a value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modules vs. Objects
&lt;/h2&gt;

&lt;p&gt;Where possible, I tends to use modules and functions over objects. For dependencies that would typically be passed into a class constructor, we just pass to the function directly (like &lt;code&gt;IHttpClientFactory&lt;/code&gt; in our example). By positioning them at the beginning of the parameter list, you'll be able to use partial application if you want to.&lt;/p&gt;

&lt;p&gt;Here's what that might look like with &lt;code&gt;execute&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;makeRequest&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="n"&gt;httpClientFactory&lt;/span&gt;    &lt;span class="c1"&gt;//only apply the first parameter&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createRequest&lt;/span&gt; &lt;span class="s2"&gt;"https://hacker-news.firebaseio.com/v0/item/8863.json"&lt;/span&gt; &lt;span class="nc"&gt;Get&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;withTimeout&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FromSeconds&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;.)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;withHeader&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&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;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;makeRequest&lt;/span&gt;    &lt;span class="c1"&gt;//pipe in the final parameter, 'request'&lt;/span&gt;
&lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RunSynchronously&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can even do the same thing with &lt;code&gt;createRequest&lt;/code&gt; if we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createRequest&lt;/span&gt; &lt;span class="s2"&gt;"https://hacker-news.firebaseio.com/v0/item/8863.json"&lt;/span&gt;

&lt;span class="k"&gt;let&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;resource&lt;/span&gt; &lt;span class="nc"&gt;Get&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="nc"&gt;Delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perhaps this is overkill, but these are the kinds of things I think about when deciding how to order the parameters — from more general to more specific; dependencies first, data second.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We were able to create a nice wrapper around &lt;code&gt;HttpClient&lt;/code&gt; that will play nicely with the rest of our code. It was no accident that we spent a good chunk of time upfront thinking about the types and the different interactions that we want our interface to support. That's the tricky part to get right; the implementation usually ends up just doing a bit of translation and delegation to the underlying library. Note that you don't have to expose the entire library — indeed, it's often easier on consumers if you just expose the stuff you actually use.&lt;/p&gt;

&lt;p&gt;Here's a &lt;a href="https://gist.github.com/jhewlett/865c11442ab383a5ada5d0c6cad174d1"&gt;gist&lt;/a&gt; that shows the full example, including some additional code for handling other HTTP methods, request bodies, and dealing with query strings&lt;sup id="fnref4"&gt;4&lt;/sup&gt;. Enjoy!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://twitter.com/isaac_abraham"&gt;Isaac Abraham&lt;/a&gt; and &lt;a href="https://twitter.com/BrettRowberry"&gt;Brett Rowberry&lt;/a&gt; for reviewing the draft of this post!&lt;/em&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;code&gt;IHttpClientFactory&lt;/code&gt; is fairly new and basically acts as a pool for &lt;code&gt;HttpClient&lt;/code&gt;s. You need to use the built-in DI container to get an instance of it. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; do overloading and optional parameters in F#, too, if you use methods rather than functions. I tend to avoid them because they don't play very nicely with type inference, and &lt;a href="https://blog.ploeh.dk/2013/10/21/replace-overloading-with-discriminated-unions/"&gt;discriminated unions are a great alternative&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Take a look at &lt;a href="https://saturnframework.org/explanations/routing.html"&gt;Saturn&lt;/a&gt; and &lt;a href="https://compositionalit.github.io/farmer/api-overview/#putting-it-all-together"&gt;Farmer&lt;/a&gt; for two good examples of using computation expressions to create DSLs. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;I have successfully used this in production, but the wrapper is by no means exhaustive. Take a look at &lt;a href="https://github.com/ronaldschlenker/FsHttp"&gt;FsHttp&lt;/a&gt; for a more fully-featured library. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>functional</category>
      <category>fsharp</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>F# Error Handling with 'Result'</title>
      <dc:creator>Justin Hewlett</dc:creator>
      <pubDate>Fri, 03 Jan 2020 15:29:47 +0000</pubDate>
      <link>https://dev.to/jhewlett/f-error-handling-with-result-35mi</link>
      <guid>https://dev.to/jhewlett/f-error-handling-with-result-35mi</guid>
      <description>&lt;p&gt;Handling errors with &lt;code&gt;Result&lt;/code&gt; is a great way to model errors in your domain and force you to consider all the error cases&lt;sup id="fnref1"&gt;1&lt;/sup&gt;. But if you're used to using exceptions for this sort of thing, it can be tricky to figure out the best way to glue all your &lt;code&gt;Result&lt;/code&gt;-returning functions together.&lt;/p&gt;

&lt;p&gt;To illustrate some different approaches, we'll go through a real-life example of making an HTTP request, checking the status code, then attempting to decode the response body.&lt;/p&gt;

&lt;p&gt;Here are the types we'll be working with to make our request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="nc"&gt;StatusCode&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="nc"&gt;RequestError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;NetworkError&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;makeHttpRequest&lt;/span&gt; &lt;span class="p"&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RequestError&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can return an &lt;code&gt;Error&lt;/code&gt; in case there's a network issue. And even if the request does succeed, we need to consider the possibility of a non-&lt;code&gt;200&lt;/code&gt; status code.&lt;/p&gt;

&lt;p&gt;Here's our &lt;code&gt;User&lt;/code&gt; type and a function to decode a string. If it fails to parse, it will return an &lt;code&gt;Error&lt;/code&gt; with a message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&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="nc"&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;decodeUser&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I deliberately left out the contents of &lt;code&gt;makeHttpRequest&lt;/code&gt; and &lt;code&gt;decodeUser&lt;/code&gt;; we're only interested in the type signatures here.&lt;/p&gt;

&lt;p&gt;The most interesting code we'll look at is the &lt;code&gt;getUser&lt;/code&gt; function below. It ties everything together and allows us to explore all the different ways to combine the error-handling logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern Matching
&lt;/h2&gt;

&lt;p&gt;We'll start with a pretty straightforward variant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;GetUserError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;NetworkError&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Non200Response&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;ParseError&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getUser&lt;/span&gt; &lt;span class="p"&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GetUserError&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="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeHttpRequest&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt;
            &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
            &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="nc"&gt;NetworkError&lt;/span&gt;
            &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StatusCode&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
                &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;decodeUser&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Body&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
                    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ParseError&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
                &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="nc"&gt;Non200Response&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use an &lt;code&gt;async&lt;/code&gt; computation expression, then pattern match to handle all the errors. This is simple and pretty easy to write, though there's a lot of nesting, and it's needlessly verbose in a few cases. All the plumbing is out there in the open, for better or worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Towards a Pipeline
&lt;/h2&gt;

&lt;p&gt;We can eliminate some of the plumbing by embracing &lt;code&gt;Result.bind&lt;/code&gt; and &lt;code&gt;Result.mapError&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getUser&lt;/span&gt; &lt;span class="p"&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GetUserError&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="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeHttpRequest&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;NetworkError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StatusCode&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
                &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Body&lt;/span&gt;
                    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;decodeUser&lt;/span&gt;
                    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapError&lt;/span&gt; &lt;span class="nc"&gt;ParseError&lt;/span&gt;
                &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="nc"&gt;Non200Response&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;&lt;code&gt;Result.bind&lt;/code&gt; chains actions together in the success case. &lt;code&gt;Result.mapError&lt;/code&gt; takes any failures that occur along the way and maps them to a common &lt;code&gt;GetUserError&lt;/code&gt; type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embrace the Pipeline
&lt;/h2&gt;

&lt;p&gt;So far we have a bit of a hybrid, using a computation expression for &lt;code&gt;async&lt;/code&gt;, and function pipelines for dealing with &lt;code&gt;Result&lt;/code&gt;. That's fine, but let's see how it feels to go all-in.&lt;/p&gt;

&lt;p&gt;Here we'll use the &lt;code&gt;AsyncResult&lt;/code&gt; module from &lt;a href="https://github.com/demystifyfp/FsToolkit.ErrorHandling"&gt;&lt;code&gt;FsToolkit.ErrorHandling&lt;/code&gt;&lt;/a&gt; which allows us to drop the &lt;code&gt;async&lt;/code&gt; computation expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getUser&lt;/span&gt; &lt;span class="p"&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GetUserError&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="n"&gt;makeHttpRequest&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;AsyncResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;NetworkError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;AsyncResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StatusCode&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Body&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;decodeUser&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapError&lt;/span&gt; &lt;span class="nc"&gt;ParseError&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="nn"&gt;AsyncResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returnError&lt;/span&gt; &lt;span class="nc"&gt;Non200Response&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not too much is different here. We use &lt;code&gt;mapError&lt;/code&gt; and &lt;code&gt;bind&lt;/code&gt; from &lt;code&gt;AsyncResult&lt;/code&gt; instead of &lt;code&gt;Result&lt;/code&gt;. We also have to use &lt;code&gt;Async.singleton&lt;/code&gt; to lift our decode &lt;code&gt;Result&lt;/code&gt; into &lt;code&gt;Async&amp;lt;Result&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nesting is pretty minimal, and it's pretty easy to see how our data flows from request to status code checking to decoding the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Computation Expressions, My Old Friend
&lt;/h2&gt;

&lt;p&gt;All right, let's see how things would look if we instead go the other way and lean harder into computation expressions. We'll use the &lt;code&gt;asyncResult&lt;/code&gt; builder from &lt;code&gt;FsToolkit.ErrorHandling&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getUser&lt;/span&gt; &lt;span class="p"&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GetUserError&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="n"&gt;asyncResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
            &lt;span class="n"&gt;makeHttpRequest&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;AsyncResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;NetworkError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StatusCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requireTrue&lt;/span&gt; &lt;span class="nc"&gt;Non200Response&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Body&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;decodeUser&lt;/span&gt;
            &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapError&lt;/span&gt; &lt;span class="nc"&gt;ParseError&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesting is eliminated completely — computation expressions are good at that. We traded in our pattern matching on &lt;code&gt;response.StatusCode&lt;/code&gt; for an interesting helper, &lt;code&gt;Result.requireTrue&lt;/code&gt;. Part of me prefers the explicit pattern matching, but &lt;code&gt;Result.requireTrue&lt;/code&gt; seems to fit the style better here.&lt;/p&gt;

&lt;p&gt;Of all the variants, this one seems to do the best job of separating the distinct phases of making the request, checking the status code, and decoding the response. Unfortunately, it also seems to give the worst compiler errors, e.g. &lt;code&gt;No overloads match for method 'Bind'&lt;/code&gt; if you forget to call &lt;code&gt;AsyncResult.mapError&lt;/code&gt; on your response &lt;code&gt;Result&lt;/code&gt;. Computation expressions are awesome, but you almost need to understand how they work under the hood to be able to understand errors like this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Which of these approaches is the best? It's not clear to me. All of the variants seem to come with their own set of trade-offs. Some are easier to write, but harder to read (and vice versa). Some are friendlier to beginners, and others use more advanced language features.&lt;/p&gt;

&lt;p&gt;But that's kind of the point. There's no one best way to do it. It depends on the context, and you need to play around with it to find something that feels right. In the end, it may come down to personal or team preference.&lt;/p&gt;

&lt;p&gt;I encourage you to get comfortable with all of the approaches I outlined. Start simple, and if you're not happy with it, then try a different approach and compare.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Scott Wlaschin has written a lot on this topic. He coined the term &lt;a href="https://fsharpforfunandprofit.com/posts/recipe-part2/"&gt;Railway Oriented Programming&lt;/a&gt; to describe this style of monadic error handling. More recently, he cautioned about taking it too far. I like his &lt;a href="https://fsharpforfunandprofit.com/posts/against-railway-oriented-programming/#when-should-you-use-result"&gt;distinction between domain errors, infrastructure errors, and panics&lt;/a&gt; as a guideline for whether you should use &lt;code&gt;Result&lt;/code&gt; or exceptions. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>fsharp</category>
      <category>dotnet</category>
      <category>ddd</category>
      <category>errors</category>
    </item>
    <item>
      <title>Dependency Injection in F# Web APIs</title>
      <dc:creator>Justin Hewlett</dc:creator>
      <pubDate>Thu, 05 Dec 2019 14:34:03 +0000</pubDate>
      <link>https://dev.to/jhewlett/dependency-injection-in-f-web-apis-4h2o</link>
      <guid>https://dev.to/jhewlett/dependency-injection-in-f-web-apis-4h2o</guid>
      <description>&lt;p&gt;I've spent a lot of time thinking about the best way to manage dependencies in F# web APIs built on top of ASP.NET Core. As you might expect from a .NET library, it makes heavy use of object-oriented patterns. For example, everything seems to be based around the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection"&gt;built-in Inversion of Control (IoC) container&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In many ways, IoC containers appear to be antithetical to the F# ethos. For one, they are a bit magical, which runs counter to the F# philosophy of being explicit. You also give up a lot of compile-time checking and have to rely on runtime failures for your dependency wire-up. Further, usually IoC containers are used with classes and interfaces, while many F# programmers &lt;a href="https://dev.to/kspeakman/mere-functional-programming-in-f-do8"&gt;favor modules, functions, and algebraic types&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, containers do give you a good way to manage resource lifetimes. &lt;em&gt;Which things should be a singleton for the duration of the server, and which things should be created once per request?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And really, since the container is built-in to ASP.NET Core, it's hard to avoid it completely. If you use the built-in configuration or logging, you'll likely need to use it. It's actually &lt;a href="https://github.com/aspnet/Extensions/issues/1345"&gt;impossible to create a &lt;code&gt;HttpClientFactory&lt;/code&gt; without using the container&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  A compromise
&lt;/h2&gt;

&lt;p&gt;I've come up with a few strategies that allow me to be a good .NET citizen and get some of the benefits of containers, such as lifetime management, without giving up my desire to wire things up manually using partial application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manual wire-up with partial application
&lt;/h3&gt;

&lt;p&gt;When registering classes, it's common to register all the parameters to a class constructor in the IoC container, then let the container construct the class automatically via reflection.&lt;/p&gt;

&lt;p&gt;The problem with this approach is that the construction of your class is now implicit. If you add a parameter to your class constructor and forget to register it, you won't get a compile error — it will just fail at runtime. I think this is one of the biggest drawbacks of containers.&lt;/p&gt;

&lt;p&gt;Instead, I &lt;a href="https://fsharpforfunandprofit.com/posts/dependency-injection-1/"&gt;use partial application&lt;/a&gt; to explicitly wire up my dependencies. Then I only register the top-level functions that will be injected into the controller.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Let's look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;Database&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;readData&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionString&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;&lt;span class="p"&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="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;'&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;list&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;personId&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a &lt;code&gt;Database.readData&lt;/code&gt; function that takes in a connection string and query and returns a list of results.&lt;/p&gt;

&lt;p&gt;Then we have a &lt;code&gt;Person.getPerson&lt;/code&gt; function that takes in a function that knows how to read data from the database and a &lt;code&gt;personId&lt;/code&gt;, executes a query, and returns the result.&lt;/p&gt;

&lt;p&gt;Notice that the &lt;code&gt;readData&lt;/code&gt; parameter in &lt;code&gt;getPerson&lt;/code&gt; is just &lt;code&gt;Database.readData&lt;/code&gt; with the connection string already baked into it via partial application.&lt;/p&gt;

&lt;p&gt;Here's what our container registration would like for this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Startup&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IConfiguration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;member&lt;/span&gt; &lt;span class="o"&gt;_.&lt;/span&gt;&lt;span class="nc"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IServiceCollection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;unit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;readData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readData&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;.[&lt;/span&gt;&lt;span class="s2"&gt;"dbConnection"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;//partially apply the connection string&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="n"&gt;readData&lt;/span&gt;    &lt;span class="c1"&gt;//partially apply the readData function&lt;/span&gt;

        &lt;span class="n"&gt;services&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetPerson&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AddControllers&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ignore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, you can register plain functions in the container!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GetPerson&lt;/code&gt; is just a type alias to a function signature; we could have just as easily inlined it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll note that we're doing all of the wiring manually via partial application&lt;sup id="fnref2"&gt;2&lt;/sup&gt;. Then, we only register the top-level function, &lt;code&gt;getPerson&lt;/code&gt;. The function &lt;code&gt;readData&lt;/code&gt; becomes a supporting function for &lt;code&gt;getPerson&lt;/code&gt;, but we have no need to register it because we won't inject it into our controller.&lt;/p&gt;

&lt;h3&gt;
  
  
  Injecting records and discriminated unions
&lt;/h3&gt;

&lt;p&gt;Injecting bare functions is simple and lightweight, but you do risk having functions with the same signature collide. For that reason, it's probably best to wrap the function in a record or &lt;a href="https://fsharpforfunandprofit.com/posts/designing-with-types-single-case-dus/"&gt;single-case discriminated union&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Option 1: Record&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;PersonControllerDependencies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//Option 2: Single-case DU&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the controller, you can inject the type into the constructor just like you would a class or interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;]&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;PersonController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PersonControllerDependencies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;inherit&lt;/span&gt; &lt;span class="nc"&gt;ControllerBase&lt;/span&gt;&lt;span class="bp"&gt;()&lt;/span&gt;

    &lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;]&lt;/span&gt;
    &lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"people/{personId}"&lt;/span&gt;&lt;span class="o"&gt;)&amp;gt;]&lt;/span&gt;
    &lt;span class="k"&gt;member&lt;/span&gt; &lt;span class="o"&gt;_.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;personId&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="n"&gt;personId&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;OkObjectResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;IActionResult&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may find it helpful to use destructuring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="n"&gt;personId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially true if you go the single-case union route because you can't just "dot" into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GetPerson&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="n"&gt;personId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What about Giraffe?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/giraffe-fsharp/Giraffe"&gt;&lt;code&gt;Giraffe&lt;/code&gt;&lt;/a&gt; is a functional web framework built on top of ASP.NET Core. Interestingly, &lt;code&gt;Giraffe&lt;/code&gt; doesn't do anything to try to hide or work around the IoC container. In your handlers, you use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GetService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a service locator pattern. In some ways, this is worse than using stock MVC because at least with MVC you have a constructor to inject your dependencies into. For this reason, I like to add in &lt;a href="https://github.com/Zaid-Ajaj/Giraffe.GoodRead"&gt;&lt;code&gt;Giraffe.GoodRead&lt;/code&gt;&lt;/a&gt;, which provides a slick way of injecting the dependencies into your request handler functions.&lt;/p&gt;

&lt;p&gt;For contrast, here is what the request handler would look like with &lt;code&gt;Giraffe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;GetPersonDependencies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;getPersonHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;GetPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;personId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="n"&gt;personId&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StartAsTask&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;webApp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;choose&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;routef&lt;/span&gt; &lt;span class="s2"&gt;"/people/%s"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;personId&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="c1"&gt;//inject the dependency into getPersonHandler&lt;/span&gt;
            &lt;span class="nn"&gt;Require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetPersonDependencies&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;getPersonDeps&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;getPersonHandler&lt;/span&gt; &lt;span class="n"&gt;getPersonDeps&lt;/span&gt; &lt;span class="n"&gt;personId&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;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I mentioned a few different approaches here. Let me give you a more concrete recommendation if you're still not sure where to start.&lt;/p&gt;

&lt;p&gt;I recommend starting with stock MVC Web API first, especially for a simple app. Use partial application in &lt;code&gt;ConfigureServices&lt;/code&gt; and inject a record of top-level functions. Records provide a nice grouping of related functions&lt;sup id="fnref3"&gt;3&lt;/sup&gt; and provide an easy way to access the functions inside.&lt;/p&gt;

&lt;p&gt;As your app grows and you become more comfortable, or if you anticipate needing request handler pipelines that compose easily, &lt;code&gt;Giraffe&lt;/code&gt; with &lt;code&gt;GoodRead&lt;/code&gt; is a good next step.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post is part of the &lt;a href="https://sergeytihon.com/2019/11/05/f-advent-calendar-in-english-2019/"&gt;F# Advent Calendar 2019&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;It occurs to me that this strategy gives you less flexibility in managing lifetimes since you're not registering all the intermediate functions. I acknowledge this and am not sure how much of a problem this is in practice. It's also worth keeping in mind that you can manage lifetimes yourself outside of an IoC container. For example, you could have a singleton factory function that, when called, created a new resource every time. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Well, most of it. The framework is still constructing the controllers themselves for us. If you really want to, you can create the controllers manually, too. &lt;a href="https://github.com/dotnetjunkie/Missing-Core-DI-Extensions/blob/master/src/SampleApplication.PureDI/Startup.cs#L34"&gt;Here's a good example&lt;/a&gt; of how to do this in C#. I haven't played around with this much, so I'm not sure whether it's worthwhile. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Yes, a record of functions is basically equivalent to an interface. Those will work fine too, especially if you pair them with &lt;a href="https://fsharpforfunandprofit.com/posts/object-expressions/"&gt;object expressions&lt;/a&gt; to implement the interface, but I prefer records because it's easy to remember the syntax to declare and create them. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>fsharp</category>
      <category>api</category>
    </item>
  </channel>
</rss>
