I would like to know the best way to interact with C# code from F# in a functional way, when I have to check null many times.
From C#, is easy because I have null operator
public bool Authorize(DashboardContext dashboardContext)
{
var context = new OwinContext(dashboardContext.GetOwinEnvironment());
var user = context.Authentication.User;
return user?.Identity?.IsAuthenticated ?? false;
}
From F#, I made this
let authorize (ctx:DashboardContext) =
match OwinContext(ctx.GetOwinEnvironment()) with
| null -> false
| c -> match c.Authentication.User with
| null -> false
| user -> user.Identity.IsAuthenticated
But I am not happy with this. What is the functional way for doing this right? I thought maybe some computation expression would help, but I don't know how to accomplish yet.
Option.ofObj
will convert a nullable object into an Option
. Then you can use the helpers already defined in the Option
module. For example, part of the pattern that you've written there is already encapsulated by Option.bind
.
let authorize (ctx:DashboardContext) =
ctx.GetOwinEnvironment() |> OwinContext |> Option.ofObj
|> Option.bind (fun c -> c.Authentication.User |> Option.ofObj)
|> Option.map (fun user -> user.Identity.IsAuthenticated)
|> Option.defaultValue false
Option.bind
takes an Option<'a>
and a function that takes the type 'a
and returns an Option<'a>
. When it is used in a pipeline it's a way of "mapping" a Some
or filtering it out into a None
.
I would say that the function you wrote looks fine actually, but this way might be considered a little bit more idiomatic, though it's arguably also a bit harder to follow in this example. Option.bind
really comes into its own when it saves multiple levels of nesting.
It's worth noting that in both your F# function and mine we're assuming non-nullness of the Authentication
and Identity
properties and risking null reference exceptions when accessing their properties. That's in contrast to the C# method using null propagation. There isn't currently a built-in way to do that in F# but there are probably some advanced methods for simulating it.
It is also possible to do this with computation expressions. See the MaybeBuilder
here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With