1 poin oleh GN⁺ 2024-11-11 | 1 komentar | Bagikan ke WhatsApp
  • F# 9 yang disertakan dalam .NET 9 mengurangi masalah keamanan yang muncul dalam interoperabilitas C#/.NET melalui nullable reference types dan peningkatan diagnostik compiler
  • Properti .Is* pada discriminated union, partial active pattern yang mengembalikan bool, serta computation expression kosong membuat sintaks F# sehari-hari menjadi lebih ringkas
  • FSharp.Core menambahkan fungsi acak untuk koleksi dan dukungan collection expression C#, sehingga koleksi immutable F# lebih mudah digunakan juga di kode .NET lain
  • Compiler mengungkap lebih dini masalah seperti penggunaan attribute yang keliru, method IL yang melebihi 65.520, dan visibilitas private member
  • Dengan optimisasi pemeriksaan equality, rentang integer, serta list/array comprehension, sebagian loop menjadi 1,25×~8×, dan sebagian array comprehension hingga 10× lebih cepat

F# 9 yang disediakan di .NET 9

  • F# 9 mencakup perubahan untuk membuat program lebih aman, lebih tangguh, dan lebih berkinerja
  • Dapat digunakan di .NET 9, dan .NET SDK terbaru bisa diperoleh dari halaman unduhan .NET
  • Perubahan utama dikembangkan di F# open source code repository

Perubahan fitur bahasa

  • Nullable reference types

    • F# dirancang untuk menghindari null, tetapi saat digunakan bersama library .NET yang ditulis dengan C#, null bisa masuk
    • F# 9 mengekspresikan reference type yang valid bernilai null secara type-safe, seperti string | null
    • Jika memasukkan null ke string atau langsung mengakses .Length dari nilai string | null, akan muncul peringatan kemungkinan null
    • Jika case null ditangani lebih dulu dalam pattern matching, binding setelahnya diperlakukan sebagai nilai non-null
    • Dalam kode generik, untuk mengembalikan null diperlukan constraint reference type seperti 'T : not struct
    • Detailnya dapat dilihat di Nullable Reference Types in F# 9
  • Properti .Is* pada discriminated union

    • Discriminated union memiliki properti .Is* yang dibuat otomatis untuk setiap case
    • Misalnya, jika tipe Contact memiliki case Email dan Phone, Anda bisa memeriksa apakah itu case tertentu dengan person.contact.IsEmail
    • Sebelumnya, untuk pemeriksaan yang sama perlu menulis kode seperti Email _ -> true | _ -> false dengan ekspresi match
  • Partial active pattern yang mengembalikan bool

    • Partial active pattern sebelumnya harus mengembalikan Some () saat pencocokan berhasil dan None saat gagal
    • Di F# 9, pengembalian bool juga diizinkan
    • Dalam contoh pencocokan string tanpa membedakan huruf besar-kecil, hasil String.Equals(..., StringComparison.OrdinalIgnoreCase) bisa dikembalikan apa adanya
  • Extension method diprioritaskan saat ada argumen

    • Sebagian library .NET mendefinisikan extension method dengan nama yang sama seperti properti bawaan suatu tipe
    • F# 9 menyesuaikan pola ini: ketika argumen diberikan, ia menafsirkan extension method alih-alih gagal saat type checking
    • Dalam contoh, extension method X(f: Foo, i: int) yang namanya sama dengan properti X milik Foo dapat dipanggil dalam bentuk f.X(1), sehingga pengaturan properti dan chaining pemanggilan bisa dilakukan
  • Computation expression kosong

    • F# 9 mendukung computation expressions kosong
    • seq { } membuat sequence kosong, dan dalam kode seperti HTML DSL dapat mengekspresikan blok kosong seperti p { }
    • Computation expression kosong mengarah ke pemanggilan method Zero milik builder
    • Ini adalah sintaks yang lebih natural dibanding builder { () } sebelumnya

Peningkatan hash directive dan F# Interactive

  • Argumen hash directive non-string

    • Hash directive compiler sebelumnya hanya mengizinkan argumen string yang diapit tanda kutip
    • Di F# 9, directive dapat menerima argumen bertipe apa pun
    • Anda bisa menulis #nowarn 0070 alih-alih #nowarn "0070", dan #time on alih-alih #time "on"
  • #help yang diperluas di F# Interactive

    • Directive #help di F# Interactive menampilkan dokumentasi objek atau fungsi di REPL
    • Argumen dapat diberikan tanpa tanda kutip
    • Misalnya, #help List.map;; menampilkan deskripsi, parameter, nilai balik, contoh, nama lengkap, dan informasi assembly
    • Detailnya dapat dilihat di Enhancing #help in F# Interactive blog post
  • Prefiks FS diizinkan pada #nowarn

    • Sebelumnya, penulisan seperti #nowarn "FS0057" menyebabkan error Invalid warning number 'FS0057' meski nomor peringatannya benar
    • Di F# 9, nomor peringatan diizinkan meski memiliki prefiks FS
    • #nowarn 57, #nowarn 0057, #nowarn FS0057, serta bentuk string "57", "0057", "FS0057" semuanya berfungsi
    • Di dalam proyek, sebaiknya pertahankan gaya yang sama

Peningkatan keamanan dan diagnostik compiler

  • Peringatan posisi [<TailCall>] yang keliru

    • F# 9 mengeluarkan peringatan jika attribute [<TailCall>] ditempelkan pada posisi yang tidak sesuai
    • Contohnya mencakup kasus ditempelkan pada fungsi non-rekursif, nilai let binding, dan nilai recursive let binding
    • Attribute seperti ini tidak memengaruhi perilaku kode, tetapi bisa membingungkan pembaca
  • Penerapan AttributeTargets diperketat

    • Compiler menegakkan AttributeTargets dengan benar pada nilai let, fungsi, deklarasi union case, constructor implisit, struct, dan class
    • Ini dapat mencegah bug yang sulit terlihat, seperti lupa menambahkan argumen unit dalam pengujian Xunit
    • Sebelumnya, [<Fact>] let ``this test always fails`` = Assert.True(false) bukan fungsi sebenarnya sehingga diabaikan oleh test runner, dan lolos saat dotnet test dijalankan
    • Sekarang muncul error error FS0842: This attribute is not valid for use on this language element
  • Pemulihan parser

    • Peningkatan pemulihan parser membuat fitur tooling seperti syntax highlighting tetap bekerja saat kode yang sedang diedit belum lengkap secara sintaksis
    • Target pemulihan mencakup pattern as yang belum lengkap, object expression, deklarasi enum case, deklarasi record, pattern primary constructor yang kompleks, unresolved long identifier, clause match kosong, serta field union case dan tipe field yang hilang
  • Akurasi pesan dan lokasi diagnostik

    • F# 9 menambahkan pesan diagnostik baru dan lokasi diagnostik yang lebih akurat
    • Targetnya mencakup method override yang ambigu pada object expression, abstract member dalam class non-abstract, properti dengan nama yang sama seperti case discriminated union, ketidaksesuaian jumlah argumen active pattern, union dengan field duplikat, penggunaan use! dan and! bersama dalam computation expression, dan lainnya
    • Class dengan method yang melebihi 65.520 dalam IL yang dihasilkan akan memunculkan error compile-time baru
    • Class seperti ini tidak dapat dimuat oleh CLR, sehingga akan berujung pada error runtime
  • Opsi visibilitas nyata

    • F# memiliki karakteristik mencatat private member sebagai internal di IL, sehingga proyek non-F# yang dapat mengakses proyek F# melalui InternalsVisibleTo bisa mengakses private member secara tidak semestinya
    • F# 9 menyediakan flag compiler --realsig+ sebagai opsi opt-in untuk memperbaiki perilaku ini
    • Di .fsproj, fitur ini dapat digunakan dengan menambahkan <RealSig>true</RealSig>
    • Anda dapat memeriksa apakah solusi bergantung pada perilaku lama

Perubahan standard library FSharp.Core

  • Fungsi acak untuk koleksi

    • Modul List, Array, dan Seq menambahkan fungsi sampling acak dan shuffle
    • Penggunaan F# menjadi lebih mudah dalam skenario umum yang membutuhkan randomness, seperti data science, machine learning, dan pengembangan game
    • Semua fungsi memiliki tiga varian
      • Varian yang menggunakan instance Random bersama yang implisit dan thread-safe
      • Varian yang menerima instance Random sebagai argumen
      • Varian yang menerima fungsi randomizer kustom yang harus mengembalikan nilai float dari 0.0 hingga kurang dari 1.0
    • Fungsi yang disediakan adalah empat fungsi: Shuffle, Choice, Choices, dan Sample, masing-masing dengan tiga varian
    • Daftar lengkap fungsi dan variannya dapat dilihat di RFC #1135
  • Perilaku tiap fungsi acak

    • Shuffle mengembalikan koleksi baru dengan tipe dan ukuran yang sama, dan setiap item diacak dengan bobot merata terhadap panjang koleksi
    • Untuk array, ada juga varian InPlace yang mengacak item di dalam array yang sudah ada
    • Choice mengembalikan satu elemen acak dengan bobot merata terhadap ukuran koleksi
    • Choices memilih N elemen dari koleksi input dalam urutan acak, dan elemen yang sama dapat dipilih beberapa kali
    • Sample memilih N elemen dari koleksi input dalam urutan acak, tetapi tidak memilih elemen yang sama dua kali
    • Pada Sample, N tidak boleh lebih besar dari panjang koleksi
  • Constructor tanpa argumen untuk CustomOperationAttribute

    • Constructor tanpa argumen ditambahkan ke CustomOperationAttribute, sehingga lebih mudah membuat operasi kustom pada computation expression builder
    • Dalam kebanyakan kasus, nama eksplisit sama dengan nama method, sehingga [<CustomOperation>] dapat digunakan alih-alih [<CustomOperation("bar")>]
  • Dukungan collection expression C#

    • Di C#, list dan set F# dapat diinisialisasi dengan collection expression
    • Misalnya, alih-alih SetModule.FromArray([1, 2, 3]), Anda bisa menulis FSharpSet<int> mySet = [ 1, 2, 3 ];
    • Koleksi immutable F# dapat digunakan saat membutuhkan structural equality yang tidak ada pada koleksi System.Collections.Immutable

Peningkatan performa

  • Optimisasi pemeriksaan equality

    • Pemeriksaan equality menjadi lebih cepat dan alokasi memori berkurang
    • Contoh mencari nilai yang tidak ada dengan Array.contains pada array tipe struct sebelumnya melakukan boxing 1.000 kali, tetapi sekarang tidak melakukan boxing
    • Dalam benchmark fungsi array untuk struct 2-member, waktu rata-rata ArrayContainsNonexisting turun dari 5.190,95ns menjadi 766,005ns, dan alokasi turun dari 24.000B menjadi 0
    • ArrayTryFindNonexisting turun dari 5.139,58ns menjadi 1.140,515ns, dan alokasi berkurang dari 24.024B menjadi 24B
    • Detailnya dapat dilihat di F# Developer Stories: How we’ve finally fixed a 9-year-old performance issue
  • Berbagi field pada struct discriminated union

    • Jika beberapa case pada struct discriminated union memiliki nama dan tipe field yang sama, field tersebut dapat berbagi lokasi memori yang sama
    • Ini mengurangi penggunaan memori struct
    • Dalam contoh, ukuran struct discriminated union yang berbagi field berbasis int64 yang sama adalah 16 byte
    • Versi yang harus memakai nama field unik untuk tiap case seperti cara lama berukuran 60 byte
    • Sebelumnya nama field yang sama tidak diizinkan, sehingga tidak ada masalah kompatibilitas biner
  • Optimisasi rentang integer

    • Compiler menghasilkan kode yang dioptimalkan untuk lebih banyak kasus ekspresi start..finish dan start..step..finish
    • Sebelumnya, optimisasi hanya berlaku jika tipenya int/int32 dan step adalah konstanta 1 atau -1
    • Tipe integer lain dan nilai step lain menggunakan implementasi berbasis IEnumerable yang tidak efisien
    • Sekarang semua kasus seperti ini dioptimalkan
    • Pada for … in start..finish do …, [start..step..finish], dan [for n in start..finish -> f n], terlihat peningkatan kecepatan 1,25× hingga 8×
  • Optimisasi list dan array comprehension

    • Bentuk for x in xs -> … pada list dan array comprehension dioptimalkan
    • Peningkatan sangat menonjol terutama pada array
    • Kecepatan meningkat hingga 10×, dan ukuran alokasi berkurang menjadi setengah hingga seperempatnya

Peningkatan tooling Visual Studio

  • Live buffers diaktifkan secara default

    • Fitur live buffers di Visual Studio sebelumnya bersifat opt-in, tetapi setelah cukup diuji kini diaktifkan secara default
    • Compiler latar belakang yang menggerakkan IDE menggunakan buffer file yang belum disimpan
    • Perubahan diterapkan tanpa perlu menyimpan file ke disk
    • Sebelumnya, perilaku tak terduga bisa terjadi saat melakukan rename pada simbol yang berada di file yang sudah diedit tetapi belum disimpan
  • Code fix untuk menghapus tanda kurung yang tidak perlu

    • Visual Studio menyediakan code fix untuk menghapus tanda kurung yang tidak perlu
    • Misalnya, let f (x) = x dapat diubah menjadi let f x = x, dan let _ = (2 * 2) + 3 menjadi let _ = 2 * 2 + 3
    • Ini mengurangi kasus saat tanda kurung lebih terasa sebagai noise daripada penjelas
  • Dukungan visualisasi kustom untuk proyek F#

    • Debugger visualizer Visual Studio juga berfungsi di proyek F#
  • Signature tooltip di tengah pipeline

    • Sebelumnya, jika parameter curried yang kompleks sudah diterapkan pada fungsi di tengah pipeline, signature help tidak tersedia
    • Sekarang signature tooltip untuk parameter berikutnya ditampilkan

1 komentar

 
GN⁺ 2024-11-11
Komentar Hacker News
  • F# terus menjadi bahasa favorit saya sejak pertama kali mengenalnya di universitas
    F# jauh lebih maju daripada C# dalam fitur seperti union, null safety, pattern matching, record, type inference yang lebih kuat, dan batasan generic
    Bagus juga C# akhirnya mengadopsi fitur-fitur seperti ini seiring waktu, tetapi sayang cara masuknya tidak saling kompatibel
    Karena investasi pada F# jauh lebih kecil daripada C#, ada sisi yang tertinggal dalam laju inovasi, tetapi F# tetap bahasa yang luar biasa, umumnya kompatibel dengan ekosistem .NET, dan bisa menghasilkan performa yang sama dengan C# dengan boilerplate yang jauh lebih sedikit

    • Sebagian besar ketidakkompatibelannya bisa diringkas menjadi source generators dan alat lain berbasis pembuatan kode
      Ini cukup mudah ditangani dengan menulis proyek C# pendamping yang berisi “kode perekat” yang diperlukan
      Selain itu, saya penasaran apakah ada masalah spesifik lain yang Anda pikirkan
      F# 9 juga mendukung penggunaan argumen generic ref struct yang baru-baru ini ditambahkan ke C#, dan setahu saya ada rencana untuk memperkenalkan fitur yang didefinisikan di F# sendiri
      Sejauh ini mereka sudah melakukan pekerjaan mengejar ketertinggalan dengan sangat mengesankan, dan pantas mendapatkan jauh lebih banyak pengakuan
  • Bagian yang mengatakan “kelas dengan lebih dari 65.520 metode dalam IL yang dihasilkan kini akan memunculkan error compile-time baru. Kelas seperti itu tidak bisa dimuat oleh CLR sehingga menimbulkan error runtime” benar-benar sulit dibayangkan
    Bagaimanapun, F# adalah bahasa yang hebat
    Menurut saya ini hal terbaik kedua yang pernah Microsoft keluarkan setelah Excel, dan menjadikan .NET sebagai platform yang masuk akal

    • Saya merasa C# cukup diremehkan
      Relatif mudah diajarkan kepada orang yang sudah terbiasa dengan JS atau TS, dan juga bahasa yang produktif
      Dipakai dalam berbagai konteks, mulai dari game engine, backend enterprise, hingga aplikasi desktop
      Menurut saya Microsoft sempat melakukan beberapa kesalahan di awal yang memperlambat pertumbuhannya, tetapi sebagai bahasa serbaguna C# benar-benar bagus dan relatif mudah dipelajari
    • Saya penasaran apa yang Anda lihat sebagai kelemahan F#
      Beberapa tahun lalu saya sempat mencobanya sebentar dengan IDE ringan bernama LINQPad, tetapi setelah itu tidak terus mengikuti kelebihan, kekurangan, atau perkembangannya
      https://www.linqpad.net/
  • Di Phosphor, kami mengambil keputusan besar selama beberapa tahun untuk mempertaruhkan arah perusahaan dan teknologi di atas F#
    Setelah mencoba lebih dari setahun, kami menulis ulang aplikasi sepenuhnya dengan TypeScript dan Rust
    Produk yang kami buat adalah alat pemrograman untuk pengguna akhir, sehingga batas tradisional frontend/backend menjadi kabur, dan ekosistem .NET tidak cocok untuk itu
    Awalnya kami ingin mengompilasi kode F# ke JS, Rust, .NET, dan lainnya dengan Fable agar bisa menjaga type safety di antara berbagai teknologi dan melakukan interoperabilitas yang diperlukan
    Dalam praktiknya, interoperabilitas antarberbagai library jauh lebih sulit dari perkiraan, dan mengelola serta memperbarui banyak dependensi dan binding benar-benar menyakitkan
    Saya tetap berpikir premis bahwa F# menghasilkan kode yang indah dan efisien itu benar, tetapi dari sisi ekosistem dan cara desainnya, F# menurut saya hanya cocok untuk aplikasi dengan batas frontend/backend tradisional yang jelas
    Jika demikian, F# kemungkinan hanya akan dipakai di backend
    Teknologi yang paling saya nantikan sekarang adalah Effect dan Moonbit yang kami gunakan secara internal
    Library Schema milik Effect menutup banyak celah dalam sistem tipe TS, dan Moonbit terlihat seperti F# modern yang lepas dari ketergantungan MS/.NET
    Moonbit dirancang oleh pembuat ReScript, yang bisa dibilang Fable untuk OCaml, dirancang dengan sangat baik, dan dikompilasi langsung menjadi output JS, WASM, dan native yang teroptimasi
    Effect sudah kami pakai di lingkungan produksi, sedangkan Moonbit belum, tetapi potensinya sebagai bahasa yang dibuat untuk dunia yang mengutamakan AI cukup luar biasa

    • Mengompilasi kode F# dan mengeksposnya sebagai modul TypeScript adalah pengalaman yang baik
      Logika bisnis inti dan validator ditulis dalam F#, sementara sisa aplikasi frontend ditulis dengan TypeScript dan backend dengan C#
      Dengan kata lain, hanya logika inti dan validasi yang ditempatkan di F#, sedangkan semua input/output ditangani oleh TS dan C#
    • Saya penasaran apakah perusahaannya ada kaitan dengan Darklang
      Saya ingat produknya mirip dan ditulis dengan F#, tetapi saya tidak mengikuti perkembangan terbarunya
      Effect cukup bagus, dan saya berharap ada juga untuk bahasa selain TypeScript
      MoonBit terlihat seperti bahasa pemrograman proprietary miliknya sendiri, jadi saya agak ragu untuk berpindah ke sana alih-alih bahasa yang sudah dikenal luas; saya penasaran bagaimana Anda melihat bagian itu
  • Saya pernah mengikuti kelas kriptografi yang membolehkan memilih bahasa apa saja selama memakai .NET, dan tugas yang saya kerjakan dengan F# jauh lebih mudah dibaca daripada milik orang lain
    Saya ingin lebih sering memakainya, tetapi pekerjaan data science hampir 100% memakai Python

  • F# 9 juga mendapat manfaat dari hampir semua peningkatan performa .NET 9 itu sendiri
    Terutama peningkatan di sisi object escape analysis yang besar
    https://devblogs.microsoft.com/dotnet/performance-improvemen...

  • Saya benar-benar merindukan masa ketika bekerja dengan F#
    Karena ini bahasa yang produktif, mengikuti pembaruannya saja sudah menyenangkan
    Mengingat ukuran komunitas dan sikap Microsoft yang kadang tampak tidak peduli, menurut saya dukungan tooling-nya cukup baik
    Ketidaknyamanan terbesar adalah akurasi code test coverage

  • Baru-baru ini saya sempat mencoba F# sedikit, dan sebagai orang yang datang dari Python, saya sangat suka karena bisa bereksperimen macam-macam lewat REPL
    Saya penasaran apakah pengembang F# yang berpengalaman juga menggunakannya seperti itu
    Musim dingin ini saya ingin membuat proyek web backend kecil untuk lebih mengenal bahasa dan ekosistemnya
    Untuk sisi HTTP, saya dengar Oxpecker bagus, tetapi saya penasaran apakah ada rekomendasi klien atau driver PostgreSQL
    Saya tidak suka ORM
    https://lanayx.github.io/Oxpecker/

    • Ada dua kemungkinan
      https://monazita.gitlab.io/monazita/ dibuat sebagai proyek pribadi sambil belajar F#, pada dasarnya berfungsi tetapi masih ada ruang untuk dipoles, dan khusus PostgreSQL
      https://github.com/jacentino/DbFun lebih matang daripada proyek sebelumnya dan mendukung beberapa database
    • Npgsql adalah driver C# yang populer dan ada juga wrapper F#-nya
      Sebaiknya mulai dari sana
    • Sebagai pengembang yang memakai beberapa bahasa, saya sesekali punya kesempatan menggunakan F#, dan sebagian besar proof of concept saya lakukan dengan REPL
      Kalau API-nya belum jelas, bahkan di dalam codebase sebenarnya saya menekan “Send to F# interactive” untuk menjalankan dan bereksperimen di dalam modul
      Saya juga memakainya untuk mencoba library baru, melakukan benchmark cepat, atau sebagai pengganti skrip PowerShell
      Dengan shebang #!/usr/bin/env -S dotnet fsi, skrip F# bisa dibuat dapat dieksekusi, jadi saya sering menggunakannya sebagai alternatif bash/Python untuk skrip di sekitar proyek .NET yang sudah memasang dotnet-sdk
      Biasanya berjalan lebih cepat dan umumnya sama ringkasnya
      Secara pribadi, saya merasa sintaks dan idiom F# lebih cocok daripada C# untuk pemrograman REPL yang merangkai potongan-potongan kode kecil
      C# biasanya membutuhkan lebih banyak struktur berorientasi objek
  • Saya penasaran bagaimana versioning F# dilakukan
    Ada banyak peningkatan kualitas hidup yang terlihat bagus, tetapi dari sudut pandang semantic versioning tidak ada breaking compatibility sehingga perubahan versi mayor tampaknya tidak terasa dibenarkan, dan untuk proyek yang tidak memakai semantic versioning pun rasanya ini bukan lompatan fitur bahasa yang cukup besar untuk naik dari 8 ke 9
    Komentar lain menyebut .NET 9 yang baru dirilis, jadi saya penasaran apakah ini untuk menyelaraskan dengan nomor versi .NET

    • .NET dan C# belakangan ini bergerak dengan rilis yang naik satu angka setiap tahun, dan F# sepertinya mengikuti cara yang sama
      Saya tidak tahu apakah peralihannya sengaja dilakukan pada momen yang cocok dengan versi .NET, atau hanya kebetulan
      Misalnya C# merilis C# 13 untuk menyesuaikan dengan .NET 9
    • Di C# maupun F#, versi .NET merujuk pada versi tool build yang digunakan saat menjalankan dotnet build
      Ini mencakup msbuild, compiler, paket NuGet, dan sebagainya
      Misalnya tim F# bisa saja merilis perubahan bahasa di antara 8 dan 9, tetapi bahkan jika tidak, mereka tetap bisa merilis perubahan compiler atau perubahan msbuild yang karena alasan tertentu membutuhkan .NET 9
      Pengembang biasanya tinggal menaikkan kode ke versi runtime terbaru, kecuali harus menunggu .NET terbaru terpasang di lingkungan deployment
      Sekarang kebutuhan itu juga berkurang berkat perubahan MSBuild yang membuat deployment self-contained, tetapi ini tetap hal yang perlu diketahui
    • Versi .NET baru keluar setiap tahun, dan versi C# serta F# juga disejajarkan dengan versi tahunan itu
      Hanya saja C# berada 4 angka di depan
      Lagi pula, menurut saya semantic versioning terlalu dibesar-besarkan
  • Saya penasaran bagaimana keadaan F# sebagai alternatif C# untuk membuat aplikasi GUI di Windows
    Saya juga penasaran apakah ada perusahaan yang memakai F# untuk tujuan seperti ini

  • Saya belum pernah mencoba F# langsung, tetapi saat melihat-lihat, materi ini tampak sangat bagus: https://fsharpforfunandprofit.com/

    • Untuk orang yang baru mengenal F#, ini memang salah satu situs terbaik
      Bagus juga untuk pengembang C# berpengalaman maupun orang yang relatif baru belajar pemrograman
      Situs ini sekarang hampir tidak diperbarui, jadi sulit menemukan pembahasan fitur baru F# 9, tetapi artikel-artikel lamanya sangat bagus untuk memahami konsep seperti apply dan bind