在学习F#时,为什么建议在字段中指定类型而不是在赋值?

Tre*_*non 7 f# types

Learning F#教程中,有两种记录类型具有相同的字段标签集.

书籍记录

type Book = 
  { Name: string;
    AuthorName: string;
    Rating: int;
    ISBN: string }
Run Code Online (Sandbox Code Playgroud)

VHS记录

type VHS =
  { Name: string;
    AuthorName: string;
    Rating: string; // Videos use a different rating system.
    ISBN: string }
Run Code Online (Sandbox Code Playgroud)

如果您随后使用这些创建记录,则F#将假定最后一个定义是您要使用的定义(VHS).因此,在"重复标签名称"标题下,建议在"评级"标签名称中添加一个类型,如下所示:

let theFSharpQuizBook = 
  { Name = "The F# Quiz Book";
    AuthorName = "William Flash";
    Book.Rating = 5;
    ISBN = "1234123412" }
Run Code Online (Sandbox Code Playgroud)

我会认为这更清楚 - 具有赋值中指定的类型:

let theFSharpQuizBook : Book = 
  { Name = "The F# Quiz Book";
    AuthorName = "William Flash";
    Rating = 5;
    ISBN = "1234123412" }
Run Code Online (Sandbox Code Playgroud)

是否有理由不提及/建议/推荐?

pad*_*pad 6

你的想法绝对合理; 添加类型注释是F#中的常用技术.

在这种情况下,我们可以将作者的建议解释如下:

  • 建议清单并非详尽无遗.
  • Book.Rating讨论记录类型时使用更有趣.它演示了一个点,即使用一个标签名称可以消除不同记录类型的歧义.

在某些情况下,使用标签名称更自然,例如模式匹配:

let getRating { Book.Rating = r } = r
Run Code Online (Sandbox Code Playgroud)

VS

let getRating ({ Rating = r }: Book) = r
Run Code Online (Sandbox Code Playgroud)

在许多情况下,当您选择使用其中一个约定时,这是个人偏好的问题.


Mar*_*ann 6

虽然我不能说为什么在教程中没有提到它,但两者都有优点和缺点.就个人而言,我根据具体情况同时使用这两种变体以及第三种变体.

当您不需要将记录分配给变量时,第一个选项很棒,而只是想用它来启动管道,如下所示:

{   Name = "The F# Quiz Book";
    AuthorName = "William Flash";
    Book.Rating = 5;
    ISBN = "1234123412" }
|> Some
|> Option.toList
Run Code Online (Sandbox Code Playgroud)

(请原谅这个愚蠢的例子,这是一种将记录转换为具有该单个元素的列表的真正迂回方式).

另一方面,正如您所说,显式地注释let绑定的值可能更具可读性,但它要求您使用let绑定,并为记录命名.

这是第三种选择,有时也会派上用场:

let theFSharpQuizBook'' = 
  { Name = "The F# Quiz Book";
    AuthorName = "William Flash";
    Rating = 5;
    ISBN = "1234123412" } : Book
Run Code Online (Sandbox Code Playgroud)