Computation expressions vs applicative functors and what not
<p>Not entirely sure the title describes it ok, but I do have about the following code:</p>

<p>paket.dependencies:</p>

<pre><code>source https://www.nuget.org/api/v2
nuget fsharpx.extras
nuget mongodb.driver
</code></pre>

<p>some.fsx:</p>

<pre><code>#r @".\packages\MongoDB.Bson\lib\net45\MongoDB.Bson.dll"
#r @".\packages\MongoDB.Driver\lib\net45\MongoDB.Driver.dll"
#r @".\packages\MongoDB.Driver.Core\lib\net45\MongoDB.Driver.Core.dll"

#r @".\packages\FSharpX.Extras\lib\net45\FSharpX.Extras.dll"


open MongoDB
open MongoDB.Driver
open MongoDB.Bson 
open MongoDB.Bson.Serialization

open FSharpx.Choice

let private createClient (connectString:string) = MongoClient(connectString)
let CreateClient = protect createClient

let private getDb name (client:IMongoClient) = client.GetDatabase(name)
let GetDB1 name client =
    choose {
        let! c = client
        return! (protect (getDb name) c)
    }

let GetDB2 name (client:Choice&lt;IMongoClient, exn&gt;) =
    protect (getDb name)
    &lt;!&gt; client
</code></pre>

<p>The point for this "excersise" was to write GetDB2 so that it does the same as GetDB1 but use operators (applicatives?), but I am at the moment not able to turn my head to manage this.</p>

<p>The above code compiles, but the signatures for 
GetDB1 and GetDB2 are not equal, and Im obviously doing something <strong><em>not</em></strong> right.</p>

<pre><code>val GetDB1 :
  name:string -&gt;
    client:Choice&lt;#MongoDB.Driver.IMongoClient,exn&gt; -&gt;
      Choice&lt;MongoDB.Driver.IMongoDatabase,exn&gt;

val GetDB2 :
  name:string -&gt;
    client:Choice&lt;MongoDB.Driver.IMongoClient,exn&gt; -&gt;
      Choice&lt;Choice&lt;MongoDB.Driver.IMongoDatabase,exn&gt;,exn&gt;
</code></pre>

<p>I have tried several versions and orders of doing things in GetDB2 but I more or less always end at same signature as above.</p>

<p>The general idea I initially had was to write small function doing the stuff they should and then add exception handling (<strong>protect</strong>) and then "wrap" and "unwrap" accordingly. </p>

<p>That might of course not be entirely right idea too.</p>

<p>Are someone able to point me in some directions here for further studies, code examples or anything? Any comments of any type are in fact welcome at this point ;-)</p>

<p><a href="http://fsprojects.github.io/FSharpx.Extras/reference/fsharpx-choice.html" rel="nofollow noreferrer">FSharpx doc</a></p>

<p><strong>Addendum</strong></p>

<p>I think the following should be about same as above, but without the mongodb dependencies.</p>

<pre><code>#r @".\packages\FSharpX.Extras\lib\net45\FSharpX.Extras.dll"

type DataBase = 
    {
        Name: string
    }

type Client = 
    {
        connectString: string
    } with member this.GetDatabase name = {
                        Name = name
                    }

open FSharpx.Choice
let private createClient (connectString:string) = {
  connectString= connectString
}

let CreateClient = protect createClient

let private getDb name (client:Client) = client.GetDatabase name

let GetDB1 name client =
    choose {
        let! c = client
        return! (protect (getDb name) c)
    }

let GetDB2 name client =
    protect (getDb name)
    &lt;!&gt; client
</code></pre>