Moerwald
Moerwald

Reputation: 11254

F# why is cast needed?

I'm new to F# and working through this article. In this article there is a sample of the following recursive type:

type Book = {title: string; price: decimal}

type ChocolateType = Dark | Milk | SeventyPercent
type Chocolate = {chocType: ChocolateType ; price: decimal}

type WrappingPaperStyle =
    | HappyBirthday
    | HappyHolidays
    | SolidColor

type Gift =
    | Book of Book
    | Chocolate of Chocolate
    | Wrapped of Gift * WrappingPaperStyle
    | Boxed of Gift
    | WithACard of Gift * message:string

Which is used in the following way:

let wolfHall = {title="Wolf Hall"; price=20m}

let birthdayPresent = WithACard (Wrapped (Book wolfHall, HappyBirthday), "Happy Birthday")

What I don't understand: Why do I need to cast wolfHall to a Book? The compiler should know that wolfHall is a Book, and therefore a Gift, based on the beforehand let-assignment.

Thanks

Upvotes: 1

Views: 64

Answers (1)

Jim Foye
Jim Foye

Reputation: 2036

In your code, Book means two things:

  1. It's the name of the record type with two fields, title and price.
  2. It's one of the cases of the discriminated union Gift. This particular case is of type Book (the record type), and it's named Book. It doesn't have to be named the same, but it can be (and often is - the same is true of the next case, Chocolate).

So, you're not casting wolfHall. You're constructing an instance of Gift, using the particular case constructor which happens to be named the same as the type it wraps. The compiler knows the difference and usually when you're reading the code, you can tell the difference. But if it's confusing, you can certainly name that constructor something else.

Upvotes: 5

Related Questions