2

我今天刚开始学习 F#,并开始学习http://www.tryfsharp.org/Learn/getting-started#data-structures上的 F# 教程

在上面的部分中,提供了三个代码片段来解释记录和选项类型:

type Book =
  { Name: string;
    AuthorName: string;
    Rating: int option;
    ISBN: string }


let unratedEdition = 
   { Name = "Expert F#";
     AuthorName = "Don Syme, Adam Granicz, Antonio Cisternino";
     Rating = None;
     ISBN = "1590598504" }


let printRating book =
match book.Rating with
| Some rating -> 
  printfn "I give this book %d star(s) out of 5!" rating
| None -> printfn "I didn't review this book"

我以为我可以像这样应用 printRating

printRating unratedEdition

但我收到以下错误

stdin(63,13): error FS0001: This expression was expected to have type
    FSI_0005.Book    
but here has type
    FSI_0009.Book 

我有点坚持我在这里做错了什么。我完全失踪的任何明显原因?

4

2 回答 2

3

很高兴您知道如何解决问题并继续学习教程!

我认为 Try F# 中代码片段的自动加载和评估有点令人困惑。问题是您首先评估第一个片段,它定义了Bookand unratedEdition。然后,您评估重新定义的第二个片段Book- 现在,对于 F# 交互式,这是一种隐藏先前定义的不同printRating类型 - 以及在版本的Book. 你打电话时:

printRating unratedEdition

您正在调用printRatingwhich 是一个函数,它将带有类型的值的 类型作为参数(因为是从早期的交互中定义的;它不会自动更新为新类型,并且这两种类型不兼容)。Book BookunratedEditionBook

如果您对以下三个片段一一评估,您可以理解这一点:

// Snippet #1: Define first version of the 'Book' type and a value of
// this type named 'unratedEdition'
type Book =
  { Name: string; AuthorName: string; Rating: int option; ISBN: string }

let unratedEdition = 
   { Name = "Expert F#"; Rating = None; ISBN = "1590598504";
     AuthorName = "Don Syme, Adam Granicz, Antonio Cisternino"; }

// Snippet #2: Now, we re-define the 'Book' type (we could also add/remove
// fields to make it actually different, but even without that, this still
// defines a new type hiding the original one). We also define a function that
// operates on the new 'Book' type
type Book =
  { Name: string; AuthorName: string; Rating: int option; ISBN: string }

let printRating book =
  match book.Rating with
  | Some rating -> 
    printfn "I give this book %d star(s) out of 5!" rating
  | None -> printfn "I didn't review this book"

// Snippet #3: This will not work, because we are calling function taking new 
// 'Book' with old 'Book' as an argument. To make this work, you need to evaluate
// one (or the other) definition of Book, then evaluate 'unratedEdition' and then
// 'printRating' (so that the value and function operate on the same 'Book' type)
printRating unratedEdition

请注意,编辑器会抱怨上面的代码无效,因为它定义了Book两次,所以你真的只能(很容易)在 Try F# 中遇到这个问题,它会在加载新片段时擦除编辑器的内容

于 2013-05-27T10:55:20.343 回答
1

好吧,我通过一次性运行所有上述代码解决了我自己的问题。即发布所有 3 个片段加上我的

printRating unratedEdition

一起进入 REPL ,然后点击 RUN。以前我对每个单独的片段使用“加载并运行”。我想这一定是 REPL 的一些问题,或者我对 REPL 如何工作的理解有限。

编辑** 我发现自己在整个教程中多次遇到这个问题。因此,如果您有错误,并且不知道为什么,请尝试将所有相关代码插入 REPL,然后点击运行。这解决了我迄今为止遇到的所有问题。

于 2013-05-27T09:36:44.037 回答