I would like to define a default value for a discriminated union, like this:
open System.Linq
type Result =
| Ok
| Error
let results : seq<Result> = [] |> Seq.ofList
let firstResult = results.FirstOrDefault()
// I want firstResult to be Error, currently it is null.
option<'a> works in this way (firstResult would be None), so it should be possible. Thanks for your help.
Edit: I'm using SQLDataProvider and would like to write code like
let userEmail =
query {
for user in dbContext.Public.Users do
where (user.Id = 42)
select (Ok user.Email)
headOrDefault
// should result in Error
// when no user with Id=42 exists
}
My actual result type looks like this:
type Result<'a> =
| Ok of 'a
| Failure of string // Expected, e. g. trying to log in with a wrong password
| Error // Unexpected
Returning an option, the caller would not be able to differentiate between failures and errors.
In general F# avoids the concept of defaults, instead making everything as explicit as possible. It's more idiomatic to return an option and for the caller to decide what to default to for a particular use case.
The FirstOrDefault
method can only return .NET's default value for any type. So for any class it would return null
, and for a number it would return zero.
I would recommend this approach instead assuming your desired default is Ok
:
results |> Seq.tryHead |> Option.defaultValue Ok
You might be able to do this using the UseNullAsTrueValue
compilation parameter. This tells the compiler to use null
as an internal representation of one of the parameter-less cases. It is a bit of a hack (because this is meant mostly for performance optimization and here we are misusing it somewhat, but it might work).
I don't have SQL database setup to try that with the SQL provider, but the following works in memory and I think it should work with SQL too:
[<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>]
type Result<'a> =
| Ok of 'a
| Failure of string
| Error
let userEmail =
query {
for a in [1] do
where (a = 2)
select (Ok a)
headOrDefault }
If you run this, F# interactive prints that userEmail = null
, but that's fine and the following is true:
userEmail = Error
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