Come inizializzare un'unione discriminata da un'altra unione discriminata in F #?

Aug 23 2020

Con le seguenti definizioni F#, come può essere inizializzato il modello?

open System
open System.Windows

type ContactDetail = { Id: Guid; Name: string; Content: string; Text: string }
type Internet      = { Id: Guid; Name: string; Content: string; Text: string }
type PhoneNumber   = { Id: Guid; Name: string; Content: string; Text: string }
type Address       = { Id: Guid; Name: string; Content: string; Text: string }

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

        type DetailsWithId = DetailsWithId of Details * Guid

        type Model = {
          ClickCount: int
          Message: string
          Details: DetailsWithId list
        }

Più specificamente, ho bisogno che i dettagli del modello siano un elenco (o seq). Il tipo DetailsWithId è già un elenco a causa del tipo Details?

TIA

Risposte

2 TomasPetricek Aug 24 2020 at 03:30

Come spiegato nel commento, un valore del tuo Detailstipo rappresenta solo un singolo dettaglio, uno dei tanti possibili dettagli elencati. Un valore di type Details listè un elenco di dettagli (che può essere vuoto o può includere più istanze dello stesso tipo di dettaglio).

Se questo non è ciò di cui hai bisogno, sarebbe utile trovare un modello che catturi meglio la struttura del tuo dominio.

Se questo è ciò che desideri, cambierei ancora due cose sui tuoi tipi di dati:

  • Innanzitutto, ripenserei a come stai memorizzando gli ID. Nel tuo modello, hai Idcampo nei singoli record, ma poi, di nuovo, nel DetailsWithIdtipo. Suppongo che la domanda sia come copiare automaticamente l'ID dal record all'ID nel DetailsWithIdtipo. Non c'è un modo semplice per farlo, ma è meglio progettare i tuoi tipi in modo da non doverlo fare.

  • In secondo luogo, i quattro tipi di record, ad esempio ContactDetail, Internet, ecc. sono tutti uguali. Non sarebbe più facile usare un solo tipo?

Penso che lavorare con i tuoi dati sarebbe molto più semplice (a meno che non ci sia qualcosa sul tuo dominio che non hai documentato nella domanda), se usassi una definizione di tipo come questa:

type DetailKind =
    | ContactDetail 
    | Internet
    | PhoneNumber
    | Address

type Detail =
  { Id: Guid
    Name: string
    Content: string
    Text: string 
    Kind: DetailKind }

type Details = Detail list