我正在研究F#的基础知识,但我仍然不确定可能的或可用的内容。我认为应该有更好的方法来做到这一点:
我正在查看使用此代码添加类型保护的常见演示场景
type CustomerId = CustomerId of int
type OrderId = OrderId of int
在某些时候,我有需要解包整数的持久性代码:
dbcmd.Execute(CID = ???, OID = ???)
选项A:笨重但有效
dbcmd.Execute(CID = match CustomerId with (CustomerId cid) -> cid, OID = match OrderId with (OrderId oid) -> oid)
选项B源自Concise pattern match on single case discriminated union in F#
中的答案这需要2行,如果有4或5件事要解开,我开始真的不喜欢距离'在let
声明的左侧和右侧之间 - 我可能最终输入无序的内容
let (CustomerId cid, OrderId oid) = (CustomerId, OrderId)
dbcmd.Execute(CID = cid, OrderId = oid)
选项C:如果没有什么比这更好的话,这可能是我更喜欢的。很明显,但比我希望的消耗更多的垂直空间
let (CustomerId cid) = CustomerId
let (OrderId oid) = OrderId
dbcmd.Execute(CID = cid, OrderId = oid)
选项D:这是我希望存在的一种。这实际上并不起作用,因为这是包装的语法,而不是解包,但是你明白了这个想法
dbcmd.Execute(CID = (CustomerId id), OID = (OrderId id))
是否存在类似于选项D的简洁语法?
答案 0 :(得分:7)
我通常使用其中一种选项,直观地在它们之间进行选择。大多数情况下,我更喜欢选项1,但如果我需要将构造函数设为私有,它就无法工作。
你可以这样做,因为功能参数不一定只是普通的标识符,它们也可以是模式。
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, ... )
答案 1 :(得分:3)
您也可以在不修改或扩展类型定义的情况下使用lambda:
cid |> fun (CustomerId i) -> i