首页 > 解决方案 > 语法:在 F# 中返回可区分联合的参数的函数?(函数参数的模式匹配)

问题描述

我显然是 F# 的新手。来自 C#,我在区分联合方面遇到了困难。

假设 F# 中有以下定义:

type Details =
            | ContactDetails of ContactDetail * id: Guid
            | Internet       of Internet  * id: Guid    
            | PhoneNumbers   of PhoneNumber  * id: Guid 
            | Addresses      of Address     * id: Guid  
    
        let contactDetail  : ContactDetail = {Name="Contact Detail"; Content="Content for Contact Detail"; Text="here is the contact detail text" }    
        let internet       : Internet = {Name="Internet";       Content="Content for Internet";       Text="here is the internet text" }
        let phoneNumber    : PhoneNumber =  {Name="Phone Number";   Content="Content for phone number";   Text="here is the phone number text" }
        let address        : Address = {Name="Address";        Content="Content for Address";        Text="here is the Address text" }
       
        let details   = [ContactDetails (contactDetail,Guid.NewGuid())
                         Internet       (internet,Guid.NewGuid())
                         PhoneNumbers   (phoneNumber,Guid.NewGuid())
                         Addresses      (address,Guid.NewGuid())
                         ]


type Model = {
      Details: Details list
    }

如何编写接收模型并返回列表中每个项目的 id 的函数?

即,类似:

有趣的细节-> detail.id

“详细信息”类型未定义字段、构造函数或成员“id”

TIA

编辑#1:

新模型是:

类型模型 = { 详细信息:DetailsWithId 列表 }

标签: f#

解决方案


可区分联合中的“已区分”意味着每个字段定义都被认为是彼此不同的,这就是为什么即使您有一个公共字段,也不能直接访问它。

我通常做的最简单的事情是创建一个安全地提取该字段的扩展函数。

type Details =
            | ContactDetails of ContactDetail * id: Guid
            | Internet       of Internet  * id: Guid    
            | PhoneNumbers   of PhoneNumber  * id: Guid 
            | Addresses      of Address     * id: Guid  

    member this.id = 
        match this with
        | ContactDetail(_, id)
        | Internet(_, id)
        | PhoneNumber(_, id)
        | Address(_, id) -> id

另一种选择是以不同的方式构建数据:

type Details =
     | ContactDetails of ContactDetail
     | Internet       of Internet
     | PhoneNumbers   of PhoneNumber
     | Addresses      of Address

// Each instance will hold one of ContactDetails, Internet, Phonenumber, and
// each has a common property of ID (the Guid). This way, you simplify your model
type DetailsWithId = DetailsWithId of Details * Guid

另一句话:您对 DU 的每个成员使用复数形式,但定义只允许一个项目。


推荐阅读