I'm working through the basics of F# and am still at the point where I'm not sure what's possible or what's available. I'm thinking there ought to be a better way to do this:
I'm looking at the common demonstration scenario of using this code for added type protection
type CustomerId = CustomerId of int
type OrderId = OrderId of int
At some point I have persistence code that needs to unwrap the integer:
dbcmd.Execute(CID = ???, OID = ???)
Option A: bulky but works
dbcmd.Execute(CID = match CustomerId with (CustomerId cid) -> cid, OID = match OrderId with (OrderId oid) -> oid)
Option B is derived from the answer in Concise pattern match on single case discriminated union in F#
This requires 2 lines and if there are 4 or 5 things to unwrap I start to really dislike the 'distance' between the left and right side of the let
statement -- I'm likely to eventually type something out of order
let (CustomerId cid, OrderId oid) = (CustomerId, OrderId)
dbcmd.Execute(CID = cid, OrderId = oid)
Option C: This is probably what I'll prefer if there's nothing better. It is clear but consumes more vertical space than I would have hoped
let (CustomerId cid) = CustomerId
let (OrderId oid) = OrderId
dbcmd.Execute(CID = cid, OrderId = oid)
Option D: This is sort of what I'm hoping exists. This doesn't actually work since this is the syntax for wrapping, not unwrapping, but you get the idea
dbcmd.Execute(CID = (CustomerId id), OID = (OrderId id))
Does concise syntax that resembles Option D exist?
I usually use one of these options, choosing between them pretty much intuitively. Mostly I prefer option 1, but it doesn't work if I need to make the constructor private.
You can do this, because function parameters don't have to be just plain identifiers, they can be patterns too.
let f (CustomerId cid) (OrderId oid) =
let cmd = ...
cmd.Execute( cid, oid )
type CustomerId = CustomerId of int
with static member toInt (CustomerId id) = id
cmd.Execute( CustomerId.toInt cid, ... )
type CustomerId = CustomerId of int
with member this.asInt = match this with (CustomerId id) -> id
cmd.Execute( cid.asInt, ... )
You could also use a lambda without modifying or extending the type definition:
cid |> fun (CustomerId i) -> i
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