簡體   English   中英

創建大型F#記錄值的最簡單方法是什么?

[英]What is the easiest way of creating a value of a large F# record?

我正在學習F#,我想知道我是否正確地接近它。 我創建了一個包含6個標簽的記錄類型,但它可以很容易地增長到10個以上的標簽。 我該如何設計它的構造函數? 由於記錄值是不可變的,我想我應該一次創建。 構造函數中的每個參數在構造值時映射到標簽。 但是,這只是錯了。

例如:

module Deal =
    open System

    type T = {
        Title : string;
        Description: string;
        NumberOfVotes: int;
        NumberOfComments: int;
        DateCreated: DateTime;
        ImageUrl: string;
    }


    let Create (title:string) (desc:string) (numberOfVotes:int) (numberOfComments:int) (dateCreated: DateTime) (imageUrl:string) =
        {
                Title = title;
                Description = desc;
                NumberOfVotes = numberOfVotes;
                NumberOfComments = numberOfComments;
                DateCreated = dateCreated;
                ImageUrl = imageUrl;
        }

我不認為隨着更多標簽添加到記錄中,構造函數可以很好地擴展。

有更好的解決方案嗎?

F#for fun and profit示例中,存儲的電子郵件地址是一個字符串,它是一個包裝類型(使用了一個有區別的聯合)。 您似乎沒有包裝類型。 這就是我如何使示例適應您的情況:

open System

type Deal =
    { Title : string; Description: string; NumberOfVotes: int
      NumberOfComments: int; DateCreated: DateTime; ImageUrl: string }

module Deal = 
    type ValidDeal =
        private ValidDeal of Deal // Note the `private` on the case constructor

    let isValid deal = true // Add implementation

    let create deal =
        if isValid deal then Some (ValidDeal deal)
        else None

    let (|ValidDeal|) (ValidDeal deal) = deal // This is an active pattern

open Deal
let f (ValidDeal d) = d // Use the active pattern to access the Deal itself.

let g d = ValidDeal d // Compile error. The ValidDeal union case constructor is private

請注意, ValidDeal union case構造函數對Deal模塊是私有的,該模塊還包含isValid函數。 因此,該模塊可以完全控制交易的驗證。 此模塊之外的任何代碼都必須使用Deal.create來創建有效的交易,如果任何函數收到ValidDeal ,則有一些編譯時保證有效性。

記錄構造通常不能很好地擴展:您需要為每個構造表達式添加其他字段。 如果您可以為其他字段分配合理的默認值,則帶有可選參數的構造函數可能會有所幫助。

open System
type Deal =
    { Title : string; Description: string; NumberOfVotes: int
      NumberOfComments: int; DateCreated: DateTime; ImageUrl: string } with
    static member Create
        (   ?title : string, 
            ?desc : string, 
            ?numberOfVotes : int, 
            ?numberOfComments : int, 
            ?dateCreated: DateTime,
            ?imageUrl : string ) =
            {   Title = defaultArg title "No title"
                Description = defaultArg desc "No description"
                NumberOfVotes = defaultArg numberOfVotes 0
                NumberOfComments = defaultArg numberOfComments 0
                DateCreated = defaultArg dateCreated DateTime.Now
                ImageUrl = defaultArg imageUrl "Default.jpg" }

雖然是更多的樣板,但可以引入其他字段而不會影響構造函數調用站點。 有兩種方法可以提供特定的參數,可以是命名參數,也可以是F#的復制和更新記錄表達式。

Deal.Create(title = "My Deal")  // named argument
{ Deal.Create() with NumberOfVotes = 42 }   // copy-and-update

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM