1 पॉइंट द्वारा GN⁺ 2024-11-11 | 1 टिप्पणियां | WhatsApp पर शेयर करें

-.NET 9 में शामिल F# 9, nullable reference types और बेहतर compiler diagnostics के ज़रिए C#/.NET interoperability से पैदा होने वाली safety समस्याओं को कम करता है

  • discriminated union .Is* properties, bool लौटाने वाले partial active patterns, empty computation expressions आदि से रोज़मर्रा का F# syntax और संक्षिप्त हो गया है
  • FSharp.Core में collections के लिए random functions और C# collection expressions support जुड़ा है, जिससे F# immutable collections को दूसरे .NET code में भी इस्तेमाल करना आसान हुआ है
  • compiler गलत attribute usage, 65,520 से ज़्यादा IL methods, private member visibility जैसी समस्याओं को पहले चरण में ही सामने लाता है
  • equality checks और integer ranges, list·array comprehension optimizations से कुछ loops 1.25×~8×, और कुछ array comprehensions अधिकतम 10× तेज़ हो गए हैं

.NET 9 में उपलब्ध F# 9

  • F# 9 में ऐसे बदलाव शामिल हैं जो programs को ज़्यादा safe, resilient और performant बनाने के लिए हैं
  • यह .NET 9 में उपलब्ध है, और latest .NET SDK .NET download page से लिया जा सकता है
  • मुख्य बदलाव F# open source code repository में develop किए गए हैं

भाषा features में बदलाव

  • nullable reference types

    • F# को null से बचने के लिए design किया गया है, लेकिन C# में लिखी .NET libraries के साथ इस्तेमाल करते समय null आ सकता है
    • F# 9 string | null की तरह ऐसे reference types जिनमें null valid है को type-safe तरीके से व्यक्त करता है
    • string में null डालने या string | null value से सीधे .Length access करने पर nullability warning आती है
    • pattern matching में अगर null case पहले handle कर लिया जाए, तो उसके बाद की binding को non-null value माना जाता है
    • generic code में null लौटाने के लिए 'T : not struct जैसी reference type constraint चाहिए
    • अधिक जानकारी Nullable Reference Types in F# 9 में देखी जा सकती है
  • discriminated union .Is* properties

    • discriminated union में हर case के लिए automatically generated .Is* property होती है
    • उदाहरण के लिए, अगर Contact type में Email और Phone cases हैं, तो person.contact.IsEmail की तरह किसी खास case की जांच की जा सकती है
    • पहले यही जांच करने के लिए match expression में Email _ -> true | _ -> false जैसा code लिखना पड़ता था
  • partial active patterns में bool return

    • partial active pattern को पहले match सफल होने पर Some (), और fail होने पर None लौटाना पड़ता था
    • F# 9 में bool return भी allow है
    • case-insensitive string matching example में String.Equals(..., StringComparison.OrdinalIgnoreCase) का result सीधे return किया जा सकता है
  • argument होने पर extension methods को प्राथमिकता

    • कुछ .NET libraries type की अपनी property के समान नाम वाला extension method define करती हैं
    • F# 9 ऐसे patterns के मुताबिक, argument दिए जाने पर type check failure के बजाय extension method resolve करता है
    • example में Foo की X property के समान नाम वाले extension method X(f: Foo, i: int) को f.X(1) रूप में call करके property setting और call chaining की जा सकती है
  • empty computation expression

    • F# 9 empty computation expressions support करता है
    • seq { } empty sequence बनाता है, और HTML DSL जैसे code में p { } जैसे empty blocks व्यक्त किए जा सकते हैं
    • empty computation expression builder के Zero method call तक जाता है
    • यह पुराने builder { () } की तुलना में ज़्यादा natural syntax है

hash directives और F# Interactive improvements

  • non-string hash directive arguments

    • compiler hash directives पहले केवल quotes में घिरे string arguments allow करते थे
    • F# 9 में arbitrary type arguments लिए जा सकते हैं
    • #nowarn "0070" के बजाय #nowarn 0070, #time "on" के बजाय #time on की तरह लिखा जा सकता है
  • F# Interactive का विस्तारित #help

    • F# Interactive का #help directive REPL में object या function documentation दिखाता है
    • arguments बिना quotes के pass किए जा सकते हैं
    • उदाहरण के लिए #help List.map;; description, parameters, return value, examples, full name और assembly information दिखाता है
    • अधिक जानकारी Enhancing #help in F# Interactive blog post में देखी जा सकती है
  • #nowarn में FS prefix allow

    • पहले #nowarn "FS0057" की तरह लिखने पर warning number सही होने के बावजूद Invalid warning number 'FS0057' error आता था
    • F# 9 में FS prefix होने पर भी warning number allow है
    • #nowarn 57, #nowarn 0057, #nowarn FS0057, और string forms "57", "0057", "FS0057" सभी काम करते हैं
    • project के अंदर समान style बनाए रखना बेहतर है

compiler safety और diagnostics improvements

  • गलत [<TailCall>] position warning

    • F# 9 में अगर [<TailCall>] attribute गलत जगह लगाया जाए, तो warning आती है
    • examples में non-recursive function, let binding value, और recursive let binding value पर लगाना शामिल है
    • ऐसे attributes code behavior पर असर नहीं डालते, लेकिन पढ़ने वाले को confuse कर सकते हैं
  • AttributeTargets enforcement मजबूत

    • compiler let values, functions, union case declarations, implicit constructors, structs और classes में AttributeTargets को सही तरीके से enforce करता है
    • Xunit tests में unit argument भूल जाने जैसे आसानी से न दिखने वाले bugs रोके जा सकते हैं
    • पहले [<Fact>] let ``this test always fails`` = Assert.True(false) असल function नहीं था, इसलिए test runner उसे ignore करता था, और dotnet test चलाने पर pass हो जाता था
    • अब error FS0842: This attribute is not valid for use on this language element error आता है
  • parser recovery

    • parser recovery improvements की वजह से editing के दौरान syntactically incomplete code में भी syntax highlighting जैसी tool features चलती रहती हैं
    • recovery targets में incomplete as patterns, object expression, enum case declaration, record declaration, complex primary constructor patterns, unresolved long identifier, empty match clauses, missing union case fields और field types शामिल हैं
  • diagnostic messages और location accuracy

    • F# 9 नए diagnostic messages और ज़्यादा accurate diagnostic locations जोड़ता है
    • targets में object expression के ambiguous override methods, non-abstract class में abstract member, discriminated union case के समान नाम वाली property, active pattern argument count mismatch, duplicate fields वाला union, computation expression में use! और and! को साथ इस्तेमाल करना आदि शामिल हैं
    • generated IL में 65,520 से ज़्यादा methods वाली class के लिए नया compile-time error आता है
    • ऐसी class CLR में load नहीं हो सकती, जिससे runtime error हो जाता है
  • वास्तविक visibility option

    • F# में private member को IL में internal के रूप में record करने की विशेषता है, जिससे InternalsVisibleTo के ज़रिए F# project तक access रखने वाले non-F# projects private members को अनुचित तरीके से access कर सकते थे
    • F# 9 इस behavior को ठीक करने वाला opt-in option, --realsig+ compiler flag देता है
    • .fsproj में <RealSig>true</RealSig> जोड़कर इसे इस्तेमाल किया जा सकता है
    • यह जांचा जा सकता है कि solution पुराने behavior पर निर्भर तो नहीं है

FSharp.Core standard library changes

  • collections random functions

    • List, Array, Seq modules में random sampling और shuffling functions जोड़े गए हैं
    • data science, machine learning, game development जैसे randomness की ज़रूरत वाले common scenarios में F# इस्तेमाल करना आसान हुआ है
    • सभी functions के तीन variants हैं
      • implicit और thread-safe shared Random instance इस्तेमाल करने वाला variant
      • Random instance को argument के रूप में लेने वाला variant
      • 0.0 या अधिक और 1.0 से कम float value लौटाने वाली custom randomizer function लेने वाला variant
    • दिए गए functions Shuffle, Choice, Choices, Sample चार हैं, और हर एक के तीन variants हैं
    • पूरी functions और variants list RFC #1135 में देखी जा सकती है
  • random functions का behavior

    • Shuffle समान type और समान size का नया collection लौटाता है, और हर item collection length के हिसाब से uniform weight के साथ shuffle होता है
    • arrays के लिए existing array के अंदर items shuffle करने वाला InPlace variant भी है
    • Choice collection size के हिसाब से uniform weight वाला एक single random element लौटाता है
    • Choices input collection से N elements random order में चुनता है, और वही element कई बार चुना जा सकता है
    • Sample input collection से N elements random order में चुनता है, लेकिन वही element दो बार नहीं चुनता
    • Sample में N collection length से बड़ा नहीं हो सकता
  • CustomOperationAttribute का parameterless constructor

    • CustomOperationAttribute में parameterless constructor जोड़ा गया है, जिससे computation expression builder की custom operations बनाना आसान हुआ है
    • अधिकतर cases में explicit name method name के समान होता है, इसलिए [<CustomOperation("bar")>] के बजाय [<CustomOperation>] इस्तेमाल किया जा सकता है
  • C# collection expressions support

    • C# में F# lists और sets को collection expression से initialize किया जा सकता है
    • उदाहरण के लिए SetModule.FromArray([1, 2, 3]) के बजाय FSharpSet<int> mySet = [ 1, 2, 3 ]; की तरह लिखा जा सकता है
    • F# immutable collections तब इस्तेमाल किए जा सकते हैं जब System.Collections.Immutable collections में न होने वाली structural equality चाहिए

performance improvements

  • equality check optimization

    • equality checks तेज़ हुए हैं और memory allocation कम हुआ है
    • struct type array में Array.contains से absent value खोजने वाला example पहले 1,000 बार boxing करता था, लेकिन अब boxing नहीं करता
    • 2-member struct पर array function benchmark में ArrayContainsNonexisting average time 5,190.95ns से 766.005ns हो गया, और allocation 24,000B से 0 हो गया
    • ArrayTryFindNonexisting 5,139.58ns से 1,140.515ns हो गया, और allocation 24,024B से 24B तक घटा
    • अधिक जानकारी F# Developer Stories: How we’ve finally fixed a 9-year-old performance issue में देखी जा सकती है
  • struct discriminated union field sharing

    • struct discriminated union के कई cases में field name और type समान हों, तो वही memory location share की जा सकती है
    • इससे struct का memory usage घटता है
    • example में समान int64-based fields share करने वाले struct discriminated union का size 16 bytes है
    • पुराने तरीके में, जहां हर case के लिए unique field name लिखना पड़ता था, version 60 bytes का था
    • पहले समान field name allow नहीं था, इसलिए binary compatibility issue नहीं है
  • integer range optimization

    • compiler start..finish और start..step..finish expressions के ज़्यादा cases में optimized code generate करता है
    • पहले केवल तब optimization होता था जब type int/int32 हो और step constant 1 या -1 हो
    • दूसरे integer types और दूसरे step values inefficient IEnumerable-based implementation इस्तेमाल करते थे
    • अब ऐसे सभी cases optimized हैं
    • for … in start..finish do …, [start..step..finish], [for n in start..finish -> f n] में 1.25× से 8× तक speed improvement दिखता है
  • list·array comprehension optimization

    • list और array comprehension में for x in xs -> … form optimized है
    • खासकर arrays में improvement notable है
    • speed अधिकतम 10× improved है, और allocation size आधे से घटकर एक-चौथाई तक हुआ है

Visual Studio tooling improvements

  • live buffers default enabled

    • Visual Studio का live buffers feature पहले opt-in था, लेकिन पर्याप्त testing के बाद default enabled कर दिया गया है
    • IDE चलाने वाला background compiler unsaved file buffers का इस्तेमाल करता है
    • file को disk पर save किए बिना भी changes apply होते हैं
    • पहले edited लेकिन unsaved file में मौजूद symbol को rename करते समय unexpected behavior हो सकता था
  • unnecessary parentheses removal code fix

    • unnecessary parentheses के लिए Visual Studio removal code fix देता है
    • उदाहरण के लिए let f (x) = x को let f x = x में, और let _ = (2 * 2) + 3 को let _ = 2 * 2 + 3 में बदला जा सकता है
    • यह ऐसे cases कम करने वाला feature है जहां parentheses clarity के लिए नहीं बल्कि noise जैसे होते हैं
  • F# projects में custom visualizers support

    • Visual Studio debugger visualizer F# projects में भी काम करता है
  • pipeline बीच में signature tooltip

    • पहले pipeline के बीच की function पर complex curried parameters पहले से applied होने पर signature help नहीं मिलती थी
    • अब अगले parameter के लिए signature tooltip दिखता है

1 टिप्पणियां

 
GN⁺ 2024-11-11
Hacker News की राय
  • F# से पहली बार यूनिवर्सिटी में परिचय होने के बाद से यह लगातार मेरी सबसे पसंदीदा भाषा रही
    unions, null safety, pattern matching, records, ज़्यादा ताकतवर type inference और generic constraints जैसी सुविधाओं में यह C# से बहुत आगे थी
    यह अच्छी बात है कि समय के साथ C# ने भी ये सुविधाएँ अपनाईं, लेकिन अफसोस है कि वे एक-दूसरे से compatible न रहने वाले तरीकों से आईं
    F# में निवेश C# की तुलना में काफी कम रहा, इसलिए innovation की रफ्तार में यह कुछ पीछे रह गई, लेकिन यह अब भी एक शानदार भाषा है, .NET ecosystem के साथ मोटे तौर पर compatible है, और C# जैसी ही performance बहुत कम boilerplate के साथ दे सकती है

    • ज़्यादातर incompatibility को source generators और दूसरे code generation आधारित tools तक सीमित मान सकते हैं
      ज़रूरी “glue code” रखने वाला एक सहायक C# project लिख दें तो इसे काफी आसानी से संभाला जा सकता है
      इसके अलावा, आपके मन में कोई खास समस्या है क्या, यह जानना चाहूँगा
      F# 9, C# में हाल में जोड़े गए ref struct generic argument के इस्तेमाल को भी support करता है, और मेरी जानकारी में F# में खुद define की जाने वाली ऐसी capability भी लाने की योजना है
      अब तक इसने catch up करने का काम प्रभावशाली तरीके से किया है, और यह कहीं ज़्यादा recognition का हकदार है
  • “Generated IL में जिस class में 65,520 से ज़्यादा methods होंगी, उसके लिए नया compile-time error आएगा। ऐसी class को CLR load नहीं कर सकता, इसलिए runtime error होता है” वाला हिस्सा कल्पना करना भी मुश्किल है
    जो भी हो, F# एक शानदार भाषा है
    Excel के बाद यह शायद Microsoft की दूसरी सबसे अच्छी चीज़ है, और .NET को एक समझदारी भरा platform बनाती है

    • मुझे लगता है C# को काफी undervalue किया जाता है
      जो लोग पहले से JS या TS से परिचित हैं, उन्हें सिखाना यह अपेक्षाकृत आसान है, और यह काफी productive भाषा भी है
      game engines, enterprise backends, desktop apps तक कई तरह के context में इसका इस्तेमाल होता है
      मेरी राय में Microsoft ने शुरुआती दौर में कुछ गलतियाँ करके इसकी growth धीमी कर दी, लेकिन general-purpose language के तौर पर यह सच में अच्छी है और सीखने में भी अपेक्षाकृत आसान है
    • जानना चाहूँगा कि आप F# की कमी क्या मानते हैं
      कुछ साल पहले LINQPad नाम के lightweight IDE में इसे थोड़ा आज़माया था, लेकिन उसके बाद इसके pros/cons या development की स्थिति पर नज़र नहीं रखी
      https://www.linqpad.net/
  • Phosphor में हमने कंपनी और तकनीकी दिशा को F# पर दाँव पर लगाने का बड़ा फैसला कई वर्षों के पैमाने पर लिया था
    एक साल से ज़्यादा कोशिश करने के बाद हमने application को TypeScript और Rust में पूरी तरह फिर से लिखा
    जो product हम बना रहे हैं वह end-user programming tool है, इसलिए पारंपरिक frontend/backend सीमाएँ धुंधली हो जाती हैं, और .NET ecosystem इसमें ठीक से fit नहीं बैठा
    मूल योजना Fable के जरिए F# code को JS, Rust, .NET आदि में compile करके अलग-अलग technologies के बीच type safety बनाए रखने और ज़रूरी interop करने की थी
    व्यवहार में अलग-अलग libraries के बीच interop उम्मीद से कहीं ज़्यादा कठिन निकला, और कई dependencies व bindings को manage और update करना सच में बेहद तकलीफदेह था
    F# सुंदर और efficient code बनाता है, यह बात मैं अब भी सही मानता हूँ, लेकिन ecosystem और design style के लिहाज से यह उन applications के लिए ही अच्छा fit लगता है जहाँ पारंपरिक frontend/backend boundary साफ हो
    ऐसे case में भी F# को सिर्फ backend में ही इस्तेमाल किया जाएगा
    इस समय जिन technologies को लेकर मैं सबसे ज़्यादा उत्साहित हूँ, वे हैं हमारे अंदर इस्तेमाल हो रहे Effect और Moonbit
    Effect की Schema library, TS type system की कई कमियों को भर देती है, और Moonbit MS/.NET dependency से बाहर निकला हुआ आधुनिक F# जैसा दिखता है
    Moonbit को ReScript के creator ने design किया है, जिसे OCaml के लिए Fable कहा जा सकता है; यह बहुत अच्छे से design किया गया है और optimized JS, WASM तथा native output में सीधे compile होता है
    Effect को हम production में इस्तेमाल कर रहे हैं और Moonbit को अभी नहीं, लेकिन AI-first दुनिया के लिए बनी भाषा के रूप में इसकी संभावना काफी जबरदस्त है

    • F# code को TypeScript modules में compile करके expose करने का तरीका अच्छा experience था
      core business logic और validators F# में लिखे, बाकी frontend app TypeScript में और backend C# में लिखा
      यानी core logic और validation ही F# में रखे, और सारा input/output TS और C# ने संभाला
    • क्या कंपनी का Darklang से कोई संबंध है, यह जानना चाहूँगा
      यह मिलता-जुलता product था और याद है कि F# में लिखा गया था, लेकिन हाल की स्थिति follow नहीं की
      Effect काफी अच्छा है, और काश यह TypeScript के अलावा दूसरी भाषाओं में भी होता
      MoonBit अपनी proprietary programming language जैसा दिखता है, इसलिए किसी well-known language की जगह वहाँ जाना थोड़ा हिचकिचाहट पैदा करता है; इस बारे में आप कैसे सोचते हैं, यह जानना चाहूँगा
  • एक cryptography class थी जिसमें .NET इस्तेमाल करने वाली कोई भी language चुन सकते थे, और F# में किया गया assignment दूसरों की तुलना में कहीं ज़्यादा पढ़ने लायक था
    इसे और अक्सर इस्तेमाल करना चाहूँगा, लेकिन data science का काम लगभग 100% Python में होता है

  • F# 9 को .NET 9 के अपने लगभग सभी performance improvements का फायदा मिलता है
    खासकर object escape analysis से जुड़े improvements बड़े हैं
    https://devblogs.microsoft.com/dotnet/performance-improvemen...

  • F# में काम करने वाला समय सच में बहुत याद आता है
    यह इतनी productive language है कि इसके updates देखते रहना भी मजेदार लगता है
    community size और Microsoft की कभी-कभी दिखने वाली उदासीनता को देखते हुए tooling support काफी अच्छा था, ऐसा मुझे लगता है
    सबसे बड़ी परेशानी code test coverage accuracy थी

  • हाल ही में F# को थोड़ा आज़माया, और Python से आने वाले व्यक्ति के तौर पर यह बात मुझे बहुत पसंद आई कि REPL में तरह-तरह के प्रयोग किए जा सकते हैं
    जानना चाहूँगा कि अनुभवी F# डेवलपर भी इसे ऐसे ही इस्तेमाल करते हैं या नहीं
    इस सर्दी में एक छोटा वेब backend project बनाकर भाषा और ecosystem को और समझना चाहता हूँ
    HTTP के लिए Oxpecker अच्छा है, ऐसा सुना है, लेकिन PostgreSQL client या driver के लिए कोई सिफ़ारिश है क्या?
    ORM मुझे पसंद नहीं हैं
    https://lanayx.github.io/Oxpecker/

    • दो संभावनाएँ हैं
      https://monazita.gitlab.io/monazita/ F# सीखते हुए निजी projects के लिए बनाया गया था; मूल रूप से काम करता है, लेकिन और पॉलिश की गुंजाइश है, और यह PostgreSQL-only है
      https://github.com/jacentino/DbFun पिछले project से ज़्यादा polished है और कई databases support करता है
    • Npgsql एक लोकप्रिय C# driver है और इसके F# wrappers भी हैं
      वहीं से शुरू करना अच्छा रहेगा
    • कई भाषाएँ इस्तेमाल करने वाले developer के तौर पर मुझे कभी-कभी F# इस्तेमाल करने का मौका मिलता है, और अधिकतर proof-of-concepts मैं REPL में करता हूँ
      अगर API स्पष्ट न हो, तो असली codebase के अंदर भी “Send to F# interactive” दबाकर module के भीतर चलाता और प्रयोग करता हूँ
      नई library आज़माने, तेज़ benchmark करने, या PowerShell scripts के replacement के रूप में भी इस्तेमाल करता हूँ
      #!/usr/bin/env -S dotnet fsi shebang से F# scripts को executable बनाया जा सकता है, इसलिए जिन .NET projects के आसपास पहले से dotnet-sdk installed है, वहाँ scripts में bash/Python के विकल्प के तौर पर इसे अक्सर इस्तेमाल करता हूँ
      आम तौर पर यह तेज़ चलता है और अक्सर उतना ही concise भी होता है
      निजी तौर पर मुझे लगता है कि F# का syntax और idioms, छोटे-छोटे code snippets जोड़कर REPL programming करने के लिए C# से बेहतर बैठते हैं
      C# में आम तौर पर ज़्यादा object-oriented structure की ज़रूरत पड़ती है
  • F# की versioning कैसे होती है, यह जानना चाहूँगा
    quality-of-life improvements तो काफी अच्छी दिखती हैं, लेकिन semantic versioning के नज़रिए से compatibility break न होने के कारण major version change जायज़ नहीं लगता, और जो projects semantic versioning नहीं अपनाते, उनके लिए भी 8 से 9 पर जाने जितनी बड़ी language-feature leap नहीं दिखती
    एक दूसरे comment में हाल में आए .NET 9 का ज़िक्र था; क्या यह .NET version numbers के साथ तालमेल बैठाने के लिए है, यह जानना चाहूँगा

    • .NET और C# हाल के समय से हर साल version को एक अंक बढ़ाने वाले releases की तरफ गए हैं, और लगता है F# भी वही तरीका अपना रहा है
      यह .NET version से मेल खाने के समय पर जानबूझकर बदला गया था या बस संयोग था, पता नहीं
      उदाहरण के लिए C# ने .NET 9 के साथ C# 13 निकाला
    • C# और F# दोनों में .NET version, dotnet build चलाते समय इस्तेमाल होने वाले build tools version को दर्शाता है
      इसमें msbuild, compiler, NuGet packages वगैरह शामिल होते हैं
      उदाहरण के लिए F# team 8 और 9 के बीच language changes जारी कर सकती थी, लेकिन अगर ऐसा न भी करती, तो किसी कारण से .NET 9 की जरूरत वाली compiler change या msbuild change जारी कर सकती थी
      अगर developers को deployment environment में latest .NET install होने का इंतज़ार नहीं करना पड़ता, तो आम तौर पर code को latest runtime version पर ले जाना ही होता है
      आजकल self-contained deployment बनाने वाले MSBuild changes की वजह से इसकी जरूरत भी कम हो गई है, लेकिन यह जानने लायक बात है
    • नया .NET version हर साल आता है और C# और F# versions भी उस annual version के साथ align होते हैं
      बस C# 4 numbers आगे है
      वैसे भी मुझे लगता है semantic versioning को जरूरत से ज़्यादा महत्व दिया जाता है
  • Windows पर GUI apps बनाते समय C# के विकल्प के रूप में F# की स्थिति कैसी है, यह जानना चाहूँगा
    यह भी जानना चाहूँगा कि क्या कोई companies F# को इस काम के लिए इस्तेमाल करती हैं

    • कुछ विकल्प हैं
      https://github.com/fsprojects/Avalonia.FuncUI
      https://fabulous.dev/ Avalonia/MAUI/Xamarin को target करता है
      https://github.com/kekyo/epoxy Avalonia और WPF support करता है
      अगर यह जानने में रुचि है कि companies इसे इस काम के लिए इस्तेमाल करती हैं या नहीं, तो आसपास पूछ सकता हूँ
  • मैंने F# खुद कभी नहीं किया है, लेकिन देखते समय यह resource बहुत अच्छा लगा: https://fsharpforfunandprofit.com/

    • F# से पहली बार परिचित होने वालों के लिए यह वाकई सबसे अच्छे sites में से एक है
      अनुभवी C# developers के लिए भी अच्छा है, और programming अपेक्षाकृत नए सीखने वालों के लिए भी
      आजकल यह बहुत कम update होता है, इसलिए F# 9 की नई features पर चर्चा मिलना मुश्किल है, लेकिन पुराने लेख apply और bind जैसे concepts समझने के लिए बेहतरीन हैं