{"id":44547,"date":"2023-02-27T10:05:00","date_gmt":"2023-02-27T18:05:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=44547"},"modified":"2023-07-05T14:19:10","modified_gmt":"2023-07-05T21:19:10","slug":"fsharp-inline-hints-visual-studio","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/fsharp-inline-hints-visual-studio\/","title":{"rendered":"Introducing F# Inline Type &amp; Parameter Name Hints in Visual Studio"},"content":{"rendered":"<p>We are constantly working on improving the F# editor experience in the Visual Studio and now we are launching a highly requested feature, Hinting. Hints for F# mean that you will no longer have to hover to get information when coding, check it out:<\/p>\n<p><div style=\"width: 800px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-44547-1\" width=\"800\" height=\"234\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/hints-demo-1.mp4?_=1\" \/><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/hints-demo-1.mp4\">https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/hints-demo-1.mp4<\/a><\/video><\/div><\/p>\n<details>\n<summary>Code<\/summary>\n<pre><code class=\"language-fsharp\">type Song = {\r\n    Artist: string\r\n    Title: string\r\n}\r\n\r\nlet whoSings song = song.Artist\r\n\r\nlet artist = whoSings { Artist = \"Arcade Fire\"; Title = \"Wake up\" }\r\n<\/code>\r\n\r\n<\/details>\r\n<h2>Overview<\/h2>\r\n<p>We currently support two kinds of hints: inline type hints and inline parameter name hints. Both are useful when the names of identifiers in code aren't intuitive. With hints, you won't need to hover over them and will see the necessary info right away.<\/p>\r\n<p>Hints are available for the majority of the F# features, including tuples and type constructors:<\/p>\r\n\r\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/overviewfsharp.png\" alt=\"Image with hints for different language elements\" width=\"1147\" height=\"510\" class=\"alignnone size-full wp-image-45049\" srcset=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/overviewfsharp.png 1147w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/overviewfsharp-300x133.png 300w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/overviewfsharp-1024x455.png 1024w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/overviewfsharp-768x341.png 768w\" sizes=\"(max-width: 1147px) 100vw, 1147px\" \/>\r\n\r\n<details>\r\n<summary>Code<\/summary>\r\n\r\n<pre><code class=\"language-fsharp\">type Song = {\r\n    Artist: string\r\n    Title: string\r\n}\r\n\r\ntype Playlist(songs) =\r\n    member this.Add(artist, title) = \r\n        { Artist = artist; Title = title } :: songs\r\n\r\nlet song1 = { Artist = \"London Grammar\"; Title = \"Lose Your Head\" }\r\nlet song2 = { Artist = \"Blur\"; Title = \"Song 2\" }\r\n\r\nlet playlist = Playlist([ song1; song2 ])\r\nlet _ = playlist.Add(\"The Big Moon\", \"Your Light\")<\/code><\/pre>\n<\/details>\n<p>Here are the hints in action for discriminated unions:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/03\/du.png\" alt=\"Image with hints for discriminated unions\" \/><\/p>\n<details>\n<summary>Code<\/summary>\n<pre><code class=\"language-fsharp\">type Genre = \r\n    | Rock of subgenre : string\r\n    | Pop of subgenre : string\r\n\r\nlet genre = Rock \"psychedelic\"\r\n\r\nlet printFullGenre = function\r\n    | Genre.Rock subgenre -&gt; $\"{subgenre} rock\"\r\n    | Genre.Pop subgenre -&gt; $\"{subgenre} pop\"<\/code><\/pre>\n<\/details>\n<p>Note that to reduce information noise in the editor, we don't show type hints when types are explicitly specified and we don't show parameter name hints when argument names coincide with parameter names:\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/03\/reduce-noise.png\" alt=\"Image demonstrating removed hints when they are considered redundant\" \/><\/p>\n<details>\n<summary>Code<\/summary>\n<pre><code class=\"language-fsharp\">type Song = {\r\n    Artist: string\r\n    Title: string\r\n}\r\n\r\nlet whoSings song = song.Artist\r\n\r\nlet song: Song = { Artist = \"London Grammar\"; Title = \"Lose Your Head\" }\r\nlet song2 = { Artist = \"Blur\"; Title = \"Song 2\" }\r\n\r\nlet artist1 = whoSings song\r\nlet artist2 = whoSings song2<\/code><\/pre>\n<\/details>\n<h2>Comparison to C# Inline Hints<\/h2>\n<p>C# has <a href=\"https:\/\/learn.microsoft.com\/visualstudio\/ide\/reference\/options-text-editor-csharp-advanced?view=vs-2022#inline-hints\">Inline Hints<\/a> for a while now. F# Hints share the same concept yet the implementation is a bit different. For example, C# type hints are displayed to the left of variables whereas F# type hints are displayed to the right of values, to follow the syntax rules in each language.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/03\/csharp-hints-versus-fsharp-hints.png\" alt=\"Image with equivalent C# and F# code with hints\" \/><\/p>\n<h2>Enable F# Hints<\/h2>\n<p>Sounds interesting? You can turn the hints on in the Advanced section of the F# options in Visual Studio Preview:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/03\/settings.png\" alt=\"Image with Visual Studio settings for F# Hints\" \/><\/p>\n<p>We are still doing some bughunting so the feature is off by default.<\/p>\n<h2>Call for contributors<\/h2>\n<p>There is much more to be done in this area! You can find the roadmap for hints in this <a href=\"https:\/\/github.com\/dotnet\/fsharp\/issues\/14157\">issue<\/a> or see all open tickets using <a href=\"https:\/\/github.com\/dotnet\/fsharp\/labels\/Area-LangService-Hints\">this query<\/a>. Among other things, we plan to bring signature hints, implement click-to-show behavior, and reduce the number of hints in obvious cases.<\/p>\n<p>We would welcome your help, many of the open tickets are <a href=\"https:\/\/github.com\/dotnet\/fsharp\/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22\">good first issues<\/a> and we also have a testing framework for hints so that you can easily verify the behavior.<\/p>\n<p>For the current implementation, big thanks go to our external contributors <a href=\"https:\/\/github.com\/kerams\">@kerams<\/a> and <a href=\"https:\/\/github.com\/rosskuehl\">@rosskuehl<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&#8217;re happy to announce a preview feature in the Visual Studio 2022 \u2013 F# Hints both type and parameter name!<\/p>\n","protected":false},"author":112074,"featured_media":45049,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,636,646],"tags":[7708,73,7707,147],"class_list":["post-44547","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-fsharp","category-visual-studio","tag-developer-experience","tag-f","tag-hints","tag-visual-studio"],"acf":[],"blog_post_summary":"<p>We&#8217;re happy to announce a preview feature in the Visual Studio 2022 \u2013 F# Hints both type and parameter name!<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/44547","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/112074"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=44547"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/44547\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/45049"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=44547"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=44547"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=44547"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}