是否有一个简洁的内联表达式来展开一个案例歧视联盟?

Cly*_*yde 6 f#

我正在研究F#的基础知识,我仍然处于不确定可能性或可​​用性的地步.我认为应该有更好的方法来做到这一点:

我正在查看使用此代码添加类型保护的常见演示场景

type CustomerId = CustomerId of int
type OrderId = OrderId of int
Run Code Online (Sandbox Code Playgroud)

在某些时候,我有需要解包整数的持久性代码:

dbcmd.Execute(CID = ???, OID = ???)
Run Code Online (Sandbox Code Playgroud)

选项A:笨重但有效

dbcmd.Execute(CID = match CustomerId with (CustomerId cid) -> cid, OID = match OrderId with (OrderId oid) -> oid)
Run Code Online (Sandbox Code Playgroud)

选项B源自F#中单个案例区分联合的简明模式匹配中的答案

这需要2行,如果有4或5件事要解开,我开始真的不喜欢let声明左右之间的"距离" - 我最终可能会输入一些乱序

let (CustomerId cid, OrderId oid) = (CustomerId, OrderId)
dbcmd.Execute(CID = cid, OrderId = oid)
Run Code Online (Sandbox Code Playgroud)

选项C:如果没有更好的选择,这可能是我更喜欢的.很明显,但消耗的垂直空间比我希望的要多

let (CustomerId cid) = CustomerId
let (OrderId oid) = OrderId
dbcmd.Execute(CID = cid, OrderId = oid)
Run Code Online (Sandbox Code Playgroud)

选项D:这是我希望存在的一种.这实际上不起作用,因为这是包装的语法,而不是解包,但你明白了

dbcmd.Execute(CID = (CustomerId id), OID = (OrderId id))
Run Code Online (Sandbox Code Playgroud)

是否存在类似于选项D的简洁语法?

The*_*Fox 8

您还可以使用 lambda 而不修改或扩展类型定义:

cid |> fun (CustomerId i) -> i
Run Code Online (Sandbox Code Playgroud)


Fyo*_*kin 7

我通常使用其中一种选项,直观地在它们之间进行选择.大多数情况下,我更喜欢选项1,但如果我需要将构造函数设为私有,则它不起作用.

选项1:在参数声明中指定模式

你可以这样做,因为函数参数不必只是普通的标识符,它们也可以是模式.

let f (CustomerId cid) (OrderId oid) =
  let cmd = ...
  cmd.Execute( cid, oid )
Run Code Online (Sandbox Code Playgroud)

选项2:创建特殊的访问器功能

type CustomerId = CustomerId of int
   with static member toInt (CustomerId id) = id

cmd.Execute( CustomerId.toInt cid, ... )
Run Code Online (Sandbox Code Playgroud)

选项2b:相同,但具有实例成员

type CustomerId = CustomerId of int
   with member this.asInt = match this with (CustomerId id) -> id

cmd.Execute( cid.asInt, ... )
Run Code Online (Sandbox Code Playgroud)

  • 你也可以嵌套模式. (2认同)