繁体   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