Arthis
Arthis

Reputation: 2293

the mechanics of let! in computation expressions

I am currently working on the computation expression series of the fabulous fsharpforfunandprofit website and I have a question regarding the lesson 4 "wrapped type" of the computation series. I have tried reading a bit further , but there's an important notion I am not grasping.

Actually, I do understand the definition of bind :

member Bind : M<'T> * ('T -> M<'U>) -> M<'U>

but one thing I do not understand at this point is the magic when using it in a computation expression with let!:

For instance in :

let product'' = 
    dbresult {
        let! custId = getCustomerId "Alice"
        let! orderId = getLastOrderForCustomer "" // error!
        let! productId = getLastProductForOrder orderId 
        printfn "Product is %s" productId
        return productId
        }
printfn "%A" product''

getCustomerId "Alice" give me back M<'T> , but custId is already the unwrapped 'T and I cannot see anywhere how does this magic trick work...

Is it part of the code hidden in the let! instruction within Fsharp core assemblies? Could someone explain to me how the let! get the T' out of its wrapper?

Thanks for your explanations

Upvotes: 3

Views: 190

Answers (1)

Random Dev
Random Dev

Reputation: 52280

this:

let product'' = 
    dbresult {
        let! custId = getCustomerId "Alice"
        let! orderId = getLastOrderForCustomer "" // error!
        let! productId = getLastProductForOrder orderId 
        printfn "Product is %s" productId
        return productId
        }

will desugar to something like (naming the monad type as just DB<'t>):

let product'' = 
   DB.Delay(fun () ->
       DB.Bind(getCustomerId "Alice",(fun custId ->
          DB.Bind(getLastOrderForCustomer "",(fun orderId ->
             DB.Bind(getLastProductForOrder orderId, (fun productId ->
                printfn "Product is %s" productId
                DB.Return productId)))))))

so basically you get a Bind level for each let! (you can usually ignore the Delay)

As you can see the computational expression syntax is much nicer than the nested Binds - most languages which supports monadic expressions of some sort have similar syntactic sugar - even C# (from ... in ... select aka LINQ)

Upvotes: 6

Related Questions