Tyson Williams (8) [Avatar] Offline
#1
Here is the code on page 186 that implements Apply via Bind.

public static Option<R> Apply<T, R>
   (this Option<Func<T, R>> optF, Option<T> optT)
   => optT.Bind(t => optF.Bind<Func<T, R>, R>(f => f(t)));


At first, I was confused by this because Bind expects a world-crossing function (i.e. one that, in this case, returns a value of type "Option<R>") but "f" only returns a value of type "R". Eventually I guessed (correctly) that this code utilizes an implicit cast from "R" to "Option<R>".

I downloaded the sample code to confirm this. If you explicitly lift the "R" to "Option<R>" using "Some", then C# is able to infer the type arguments to BInd. That code looks like this.


public static Option<R> Apply<T, R>
   (this Option<Func<T, R>> optF, Option<T> optT)
   => optT.Bind(t => optF.Bind(f => Some(f(t))));


It seems that the C# compiler can either determine the correct implicit cast within the expression passed into BInd or infer the type arguments to Bind but not both.

I prefer the latter. I find the explicit type arguments to be mostly distracting and the explicit lift via "Some" makes the code more closely match my expectations.
Enrico Buonanno (104) [Avatar] Offline
#2
Yes, that's correct and much better: you need to compose `f` with `Return` to make it into a world-crossing function that can be given to `Bind` smilie

I've added this to the errata