Join Kit Eason for an in-depth discussion in this video Mutually referential types and modules, part of What's New in Visual Studio 2017 for F# For Developers.
- [Instructor] Well we've done some pretty tough stuff with looking at the result type and all the implications of that. Let's take a bit of a break now, and look at some fairly simple changes to the way F Sharp lets you organize your programs. Specifically, we've got mutually referential types and modules, which is a lot less complicated than it sounds. We've got the implicit module suffix, which is something almost behind the scenes that you'll barely notice, but we'll just explain the significance of it, and we've got caller info attributes, which is a really nice way of being able to see some things about what has called a particular function, which line number and so forth, and that's useful in logging and debugging scenarios, and perhaps for tool builders.
One of the complaints of people coming from other languages like C Sharp is that F Sharp requires you to declare things in a particular order. Specifically, you need to declare something before in a particular file or in the overall structure of the solution you use it. So you declare before you use. And there aren't really any changes due to solution and file ordering, but there is a change within a file. And that is that modules and name spaces can be mutually referential. So, if we look at this kind of scenario here, and to an F Sharp developers eye this looks a little bit contrived, it perhaps feels a bit more natural to a C Sharp developer.
We've got a function called area, on line eight, that matches some shape type with either square and recovers the length side of the square and multiplies it by itself. Or on line 11, a rectangle which recovers the width and height of the rectangle and multiplies those together. And of course the reason we're getting a compiler error on line ten, if I hover over it, is that the patent discriminator, or discriminated union square, is not defined. Now, it's defined down on line 14.
That's when we tell you what a square is. And I guess the reason we define them in this order is that on line 20, we're going to provide a member of the shape type, down here, it's a member of shape called area, and it calls this stand alone area function, up here. So we're providing two ways of getting the area of a shape. One is the stand alone function that isn't really a member of anything, and one is a member function which calls our stand alone function.
So that might be a way you might want to organize things if you want to provide a natural experience for people who like dotting into methods or for people who prefer stand alone functions. But it simply doesn't work, because we're declaring things after we're using them. You won't believe how easy the fix for that is. We add the keyword rec for recursively on line five to the module and you'll see our compiler error has gone away. Alternatively, within the file, we can make the whole name space recursive, like that, and again, the error goes away.
Simple as that.
Kit Eason discusses the new value types that provide an opportunity for performance gains, the new result type which gives you access to the railway oriented programming style of error handling, and program organization and readability changes. Plus, he explores the evolution of tooling for F#, and explains how F# tooling has changed in Visual Studio 2017. To wrap up the course, he shares how you can contribute to the F# language and tooling by getting involved in the open-source community.
- Working with struct tuples
- Marking a record type as a struct value
- Marking a discriminated union as a struct type
- Using the fixed keyword to mark a value
- F# result type and associated functions
- Resolving potential naming clashes between modules and types
- Error message improvements
- The past and future of visual F# tooling in Visual Studio
- Reviewing F# tooling changes