【问题标题】:F# Optional Record FieldF# 可选记录字段
【发布时间】:2010-04-14 00:53:05
【问题描述】:

我有一个 F# 记录类型并希望其中一个字段是可选的:

type legComponents = {
    shares : int<share> ;
    price : float<dollar / share> ;
    totalInvestment : float<dollar> ;
}

type tradeLeg = {
    id : int ;
    tradeId : int ;
    legActivity : LegActivityType ;
    actedOn : DateTime ;
    estimates : legComponents ;
    ?actuals : legComponents ; 
}

在 tradeLeg 类型中,我希望实际字段是可选的。我似乎无法弄清楚,我似乎也无法在网上找到可靠的例子。看起来这应该很容易,就像

let ?t : int = None

但我似乎真的无法让它发挥作用。呃-谢谢你

T

【问题讨论】:

    标签: f# record optional


    【解决方案1】:

    正如其他人指出的那样,您可以使用 'a option 类型。但是,这不会创建可选的记录字段(创建时不需要指定其值)。例如:

    type record = 
      { id : int 
        name : string
        flag : bool option }
    

    要创建record 类型的值,您仍然需要提供flag 字段的值:

    let recd1 = { id = 0; name = "one"; flag = None }     
    let recd2 = { id = 0; name = "one"; flag = Some(true) } 
    
    // You could workaround this by creating a default record 
    // value and cloning it (but that's not very elegant either):
    let defaultRecd = { id = 0; name = ""; flag = None }     
    let recd1 = { defaultRecd  with id = 0; name = "" }
    

    不幸的是,(据我所知)您无法创建具有真正选项字段的记录,您可以在创建时省略该字段。但是,您可以将类类型与构造函数一起使用,然后您可以使用?fld 语法来创建构造函数的可选参数:

    type Record(id : int, name : string, ?flag : bool) = 
      member x.ID = id
      member x.Name = name
      member x.Flag = flag
    
    let rcd1 = Record(0, "foo")
    let rcd2 = Record(0, "foo", true)
    

    rcd1.Flag 的类型将是bool option,您可以使用模式匹配来处理它(如殷朱所示)。记录和像这样的简单类之间唯一显着的区别是您不能使用with 语法来克隆类,并且类不会(自动)实现结构比较语义。

    【讨论】:

    • 知道了! thx: type record = { i : int flag : bool option } let recd1 = { i = 0;标志 = 无 } 让 recd2 = { i = 0; flag = Some(true) } type record2 = { r1: record ; r2: 记录选项 } let recd3 = { r1 = { i = 0;标志 = 无 } ; r2 = Some({ i = 0; flag = Some(true)}) } 让 recd4 = { r1 = { i = 0;标志 = 无 } ; r2 = 无}
    • @akaphenom:cmets 中的代码不是特别可读。但我猜您使用类的示例可能如下所示:let recd4 = Record2(Record(0))(不设置r2flag)或例如设置所有属性时的recd5 = Record2(Record(0, true), Record(1, false))
    • 我知道这是 10 岁,但我认为创建一个 DU:type X = WithActuals of legComponents * tradeLeg | WithoutActuals of tradeLeg 并从主记录中删除 actuals 更习惯。这样你的代码的意图就很清楚了
    【解决方案2】:

    Option怎么样?

    type tradeLeg = {
        id : int option;
        tradeId : int option;
        legActivity : LegActivityType option;
        actedOn : DateTime option;
        estimates : legComponents option;
        actuals : legComponents option; 
    }
    

    【讨论】:

    • let me = StrangleMyself !option 我真的以为我今天下午试过了。忙着进出会议——我想我需要更好地做笔记和阅读规格。非常感谢托德
    【解决方案3】:

    作为对现有帖子的评论,以下是选项类型的示例:

    ..
    id: int option;
    ..
    
    match id with
      | Some x -> printfn "the id is %d" x
      | None -> printfn "id is not available" 
    

    您可以使用选项值来隐藏 id:

    let id = Some 10
    

    let id = None
    

    并参考此 MSDN 页面:http://msdn.microsoft.com/en-us/library/dd233245%28VS.100%29.aspx

    Here 是选项类型的另一个示例,您可能会对 Seq.unfold 感兴趣。

    【讨论】:

      【解决方案4】:
      actuals : legComponents option;
      

      【讨论】:

        猜你喜欢
        • 2015-03-21
        • 2011-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多