7 điểm bởi GN⁺ 2025-04-03 | 1 bình luận | Chia sẻ qua WhatsApp
  • F# là một ngôn ngữ hàm họ ML nhắm tới .NET, do Microsoft phát triển. So với C# vốn chủ yếu theo hướng lập trình hướng đối tượng, F# tập trung vào mô hình lập trình hàm
  • Bài viết này tổng hợp các đặc điểm ngôn ngữ, hệ sinh thái, tình trạng tài liệu hóa, công cụ phát triển, trường hợp sử dụng, cộng đồng và so sánh F# với OCaml

F# là gì?

  • F# là ngôn ngữ lập trình đa dụng để viết mã ngắn gọn, chắc chắn và hiệu năng tốt
  • Được thiết kế để bạn có thể tập trung vào việc giải quyết vấn đề, thay vì bận tâm đến cú pháp phức tạp
  • Mã nguồn mở, đa nền tảng và có khả năng tương thích rất cao với .NET
  • Đặc điểm

    • Cú pháp gọn nhẹ và tính bất biến mặc định
    • Suy luận kiểu và khái quát hóa
    • Hàm hạng nhất, kiểu dữ liệu mạnh và pattern matching
    • Hỗ trợ lập trình bất đồng bộ (Async)
    • Là ngôn ngữ khai sinh ra toán tử pipeline (|>) nổi tiếng
  • Ví dụ mã đơn giản

    open System  
    let names = [ "Peter"; "Julia"; "Xi" ]  
    let getGreeting name = $"Hello, {name}"  
    names |> List.map getGreeting |> List.iter (printfn "%s")  
    
  • F# bắt đầu là một ngôn ngữ do Don Syme phát triển tại Microsoft Research vào năm 2005
    • Khởi đầu từ dự án nghiên cứu chuyển OCaml sang nền tảng .NET (Caml.NET)
    • Sau đó được đưa vào danh mục sản phẩm chính thức từ năm 2010, và đến năm 2024 thì F# 9.0 được phát hành
    • Tính đến năm 2025, đây đã là một ngôn ngữ trưởng thành bước sang năm thứ 20
  • Những lý do chính khiến tác giả thử nghiệm F#
    • Xác nhận việc .NET đã tiến hóa thành nền tảng mã nguồn mở và đa nền tảng
    • So sánh ưu và nhược điểm với OCaml
    • Đánh giá tích cực về công cụ như Rider, Ionide
    • Hứng thú đơn thuần với việc khám phá ngôn ngữ

F# với tư cách một ngôn ngữ

  • F# là ngôn ngữ hàm họ ML, có cú pháp quen thuộc với người dùng OCaml
  • Các lập trình viên từng dùng Haskell hoặc Lisp cũng có thể thích nghi dễ dàng
  • Cấu trúc cú pháp dựa trên khoảng trắng, nên thụt lề quan trọng về mặt ngữ pháp giống như Python
  • Được thiết kế để ngay cả người mới cũng có thể nhanh chóng nắm cú pháp cơ bản
  • Tóm tắt đặc điểm ngôn ngữ

    • Định nghĩa và áp dụng hàm được biểu đạt ngắn gọn, tự nhiên
    • Câu điều kiện, vòng lặp, tuple, xử lý list đều có thể dùng theo phong cách hàm một cách gọn gàng
    • Record, discriminated union, pattern matching giúp xử lý cấu trúc dữ liệu phức tạp một cách súc tích
    • Với toán tử pipeline (|>), luồng dữ liệu có thể được tổ chức trực quan rõ ràng như chuỗi kết nối các hàm
    • F# rất phù hợp để viết script ad-hoc, có thể viết trong file .fsx rồi chạy ngay bằng dotnet fsi
    • Cũng cung cấp môi trường REPL nên thuận lợi cho lập trình khám phá
  • Cú pháp thân thiện với người dùng

    • Bao gồm các tính năng cú pháp thực dụng như chú thích một dòng và nhiều dòng, biến mutable, list slice
    • Nhờ khả năng tương thích cao với C#, có thể dùng .NET API rất dễ dàng
    • Cũng hỗ trợ tự nhiên việc nạp chồng toán tử cho nhiều kiểu khác nhau
    • printfn giúp in ra nhiều kiểu dữ liệu một cách dễ dàng, hữu ích cho debug và logging
  • Người tiên phong của lập trình bất đồng bộ

    • Nguồn gốc của mẫu async/await là F# 2.0, sau đó ảnh hưởng đến nhiều ngôn ngữ như C# và JavaScript
    • F# cung cấp cấu trúc giúp triển khai lập trình bất đồng bộ một cách trực quan mà không cần callback
    • Luồng mã trông như đồng bộ nhưng thực tế lại chạy bất đồng bộ
  • Sự đầu tư của Microsoft và tiến hóa của ngôn ngữ

    • Microsoft từng phân bổ nguồn lực khá hạn chế cho F# trong thời gian dài, nhưng từ năm 2022 đã lập đội ngũ chuyên trách tại Prague và bắt đầu đầu tư nghiêm túc
    • Qua các bản phát hành F# 8.0 và 9.0, ngôn ngữ và công cụ đang được cải thiện nhanh chóng
    • Khi sự quan tâm nội bộ của Microsoft tăng lên, cũng có thể kỳ vọng vào tiềm năng phát triển trong tương lai

F# là một ngôn ngữ thực dụng, dễ học nhưng vẫn sở hữu hệ thống kiểu mạnh và mô hình lập trình hàm; đặc biệt, đây là lựa chọn rất hấp dẫn cho các lập trình viên muốn đưa cách tiếp cận hàm vào các dự án dựa trên .NET

Hệ sinh thái (Ecosystem)

  • Sau một thời gian sử dụng tương đối ngắn, tác giả thấy rằng không có quá nhiều thư viện hay framework thuần F#
  • Phần lớn người dùng vẫn phụ thuộc vào API mặc định của .NET và các thư viện bên thứ ba chủ yếu được thiết kế quanh C#
  • Đây là hiện tượng thường thấy ở các ngôn ngữ chạy trên nền tảng chủ (hosted language) như Scala, Clojure, Groovy
  • Các thư viện chính cho phát triển web

    • Giraffe: framework web nhẹ dựa trên ASP.NET Core, hướng tới phong cách hàm
    • Suave: framework web server đơn giản theo phong cách combinator để định tuyến và tổ hợp tác vụ
    • Saturn: framework phong cách MVC xây trên Giraffe, lấy cảm hứng từ Ruby on Rails và Phoenix
    • Bolero: framework phát triển ứng dụng client dựa trên WebAssembly và Blazor
    • Fable: transpile F# sang JavaScript để có thể tích hợp với hệ sinh thái JS như React, Node.js
    • Elmish: framework UI dựa trên mẫu MVU (Model-View-Update), thường dùng cùng Fable
    • SAFE Stack: stack phát triển web hàm end-to-end kết hợp Saturn, Fable, Elmish, Azure...
  • Các thư viện chính cho khoa học dữ liệu

    • Deedle: thư viện phân tích và thao tác dữ liệu theo phong cách pandas
    • DiffSharp: thư viện thiên về toán học, cung cấp machine learning và automatic differentiation
    • FsLab: bộ công cụ khoa học dữ liệu tích hợp gồm trực quan hóa, phân tích thống kê...

Tình trạng tài liệu hóa

Công cụ phát triển (Dev Tooling)

  • Hệ sinh thái công cụ phát triển của F# trước đây chủ yếu chỉ được tối ưu cho Visual Studio, còn hỗ trợ cho các trình soạn thảo khác thì khá yếu
  • May mắn là trong 10 năm qua, môi trường công cụ đã được cải thiện đáng kể
  • Bước ngoặt kỹ thuật: FSharp.Compiler.Service (FCS)

    • FCS là một thư viện thống nhất bao gồm compiler F#, tính năng hỗ trợ trình soạn thảo và scripting engine, cho phép dùng F# trên nhiều editor và môi trường tooling khác nhau
    • Nhờ đó, hỗ trợ F# đã có thể xuất hiện trên VS Code, trình tạo tài liệu, backend thay thế... và thúc đẩy hệ sinh thái mở rộng
    • Ví dụ tiêu biểu là Ionide, mang đến hỗ trợ F# phong phú trên VS Code và đã vượt mốc 1 triệu lượt tải
  • Các editor đã thử nghiệm

    • Emacs (fsharp-mode): cung cấp chức năng cơ bản, không hỗ trợ TreeSitter, hoạt động phát triển ít
    • Zed: hỗ trợ F# còn hạn chế
    • Helix: có hỗ trợ cơ bản
    • VS Code (plugin Ionide): một trong những môi trường hoàn thiện nhất
    • JetBrains Rider: IDE thương mại nhưng hỗ trợ F# rất mạnh

    Phần lớn tính năng hoạt động dựa trên F# language server (fsautocomplete), nên mọi editor có hỗ trợ LSP tốt đều có thể dùng được

  • Điểm còn tiếc

    • fsharp-mode dựa trên codebase cũ và phát triển chậm
    • Zed còn thiếu tính năng
    • VS Code có một số tính năng (ví dụ: mở rộng/thu gọn vùng chọn) hoạt động chưa đúng
    • Một số người dùng cũng thấy VS Code bất tiện do vấn đề keybinding/mô hình modal
  • Formatter và linter cho mã

    • Fantomas: formatter mã chính thức của F#, được đa số người dùng và đội nhóm sử dụng
    • FSharpLint: từng phổ biến nhưng hiện gần như đã ngừng phát triển
    • Tuy nhiên, nhờ compiler rất mạnh, mức độ phụ thuộc vào linter là không cao
  • Công cụ khác

    • Paket: trình quản lý dependency cho .NET (tương tự npm, pip, bundler)
    • FAKE: DSL cho phép viết build script bằng F#, tương tự rake của Ruby

Trường hợp sử dụng (Use Cases)

  • Nhờ hệ sinh thái rộng lớn của .NET, F# có tiềm năng được dùng trong nhiều lĩnh vực khác nhau
  • Đặc biệt, nhờ tính năng Type Providers, F# rất phù hợp cho các tác vụ phân tích và thao tác dữ liệu
  • Cũng phù hợp cho phát triển dịch vụ backend và ứng dụng full-stack; một số công cụ còn cho phép làm cả frontend
  • Các lĩnh vực sử dụng chính

    • Phân tích dữ liệu: có thể thao tác dữ liệu dựa trên kiểu tĩnh nhờ Type Providers của F#
    • Dịch vụ backend: có thể dùng F# cùng các framework web mạnh mẽ của .NET
    • Ứng dụng frontend: thông qua Fable và Elmish, có thể phát triển UI tích hợp với hệ sinh thái JS
      • Từ Fable 4, còn có thể transpile sang nhiều ngôn ngữ như TypeScript, Rust, Python
  • Ví dụ Fable (lệnh transpile đơn giản)

    • JavaScript:
      dotnet fable
    • TypeScript:
      dotnet fable --lang typescript
    • Python:
      dotnet fable --lang python

Tình hình cộng đồng

  • Nhìn chung cộng đồng không lớn và có thể còn nhỏ hơn cả OCaml
  • RedditDiscord là hai không gian giao tiếp sôi động nhất
  • Cộng đồng Slack cũng tồn tại nhưng khó tiếp cận do vấn đề với hệ thống tự động gửi lời mời
  • Vai trò của Microsoft trong cộng đồng không thật sự rõ ràng, và cộng đồng có xu hướng tự dẫn dắt khá mạnh
  • Các nguồn lực chính đang được cộng đồng vận hành

    • Amplifying F#: thúc đẩy phổ biến F# và khuyến khích doanh nghiệp tham gia
    • F# for Fun and Profit: kho lưu trữ tutorial và bài luận
    • F# Lab: bộ công cụ cộng đồng F# cho khoa học dữ liệu
    • F# Weekly: bản tin tổng hợp tin tức F# mới nhất

Mức độ phổ biến và thực tế (The Popularity Contest)

  • F# không nằm ở thứ hạng cao trên hầu hết các thước đo độ phổ biến như TIOBE, StackOverflow hay tin tuyển dụng
  • Nhưng đây cũng là thực tế chung của phần lớn các ngôn ngữ hàm, không phải vấn đề riêng của F#
  • Dù chưa phải dòng chính, nó vẫn có nhóm người dùng ở quy mô tương đương với các ngôn ngữ hàm khác như Clojure, OCaml, Emacs Lisp
  • Vì sao dùng F#?

    • Có nhiều lý do để chọn một ngôn ngữ lập trình ngoài khả năng xin việc
      • Vì vui (cũng có câu nói chữ F trong F# là “Fun”)
      • Học các mô hình và ý tưởng mới
      • Rèn luyện cách suy nghĩ khác với tư duy quen thuộc
  • Tài liệu liên quan

So sánh F# với OCaml

Mục tiêu ban đầu của F# là mang những ưu điểm của OCaml sang .NET, và mang những ưu điểm của .NET sang OCaml
– Don Syme, người tạo ra F#

  • F# được phát triển với cảm hứng từ OCaml, và thời kỳ đầu còn tương đồng đến mức hỗ trợ cả phần mở rộng file .ml, .mli
  • Theo thời gian, nó dần tiến hóa thành một ngôn ngữ độc lập, và giờ đây mỗi bên phát triển theo hướng riêng
  • Ưu điểm của F#

    • Dựa trên nền tảng .NET
      • Có thể tận dụng số lượng thư viện khổng lồ
    • Có sự hỗ trợ của Microsoft
    • Thân thiện với người mới
      • Cú pháp quen thuộc với những ai từng dùng ngôn ngữ hướng đối tượng (như C#)
      • Thông báo lỗi của compiler tương đối rõ ràng
      • Trải nghiệm debug trực quan hơn
    • Hỗ trợ lập trình bất đồng bộ rất mạnh
    • Cung cấp những tính năng mà OCaml không có
      • Anonymous record
      • Active pattern
      • Computational expressions
      • Sequence comprehension
      • Type providers
      • Units of measure
  • Nhược điểm của F#

    • Dựa trên nền tảng .NET
      • Có nhiều thỏa hiệp trong thiết kế ngôn ngữ để tương tác với .NET (null được cho phép, v.v.)
    • Thuộc sở hữu của Microsoft
      • Mức độ yêu thích Microsoft khác nhau giữa từng người
      • Nguồn lực phân bổ cho F# vẫn tương đối ít
      • Về dài hạn, mức độ Microsoft sẽ hỗ trợ F# đến đâu vẫn còn chưa chắc chắn
    • Vấn đề liên quan đến tên gọi
      • Những ai không thích quy ước đặt tên PascalCase, camelCase có thể thấy bất tiện
      • Cái tên F# có thể gây vấn đề khi tìm kiếm hoặc đặt tên file (vì vậy cũng thường được viết là FSharp)
    • Thiếu một số tính năng nâng cao có trong OCaml
      • First-class module, functor
      • Hỗ trợ GADT còn thiếu
    • Không có mascot, cũng không có lạc đà
  • Điểm chung và so sánh qua lại

    • Cả hai ngôn ngữ đều có thể nhắm tới runtime JavaScript
      • F#: Fable
      • OCaml: js_of_ocaml, Melange
    • Hiện tại Fable cho cảm giác trưởng thành hơn, nhưng vẫn cần thêm trải nghiệm sử dụng thực tế
    • Cả hai đều mạnh nhưng là ngôn ngữ ngách, và trong tương lai gần khó có khả năng trở thành ngôn ngữ đại chúng rộng rãi
    • F# có tính thực dụng là có thể len dần vào các codebase C# sẵn có
    • Một nhược điểm là dự án F# vẫn dùng file project dựa trên XML và phải chỉ định thứ tự biên dịch thủ công
      • Điều này có thể gây cảm giác phiền hơn khi so với hệ thống build Dune của OCaml
    • Với mục đích giáo dục hoặc học cấu trúc ngôn ngữ, OCaml có thể phù hợp hơn
    • Nếu mục tiêu là phát triển dịch vụ web hoặc backend thực dụng, F# có thể là lựa chọn tốt hơn
    • Đặc biệt, với tư cách một ngôn ngữ tích hợp tốt với .NET nhưng vẫn giữ được phong cách hàm, F# là một công cụ rất mạnh

Cảm nhận kết lại

  • Tác giả cảm thấy F# là một ngôn ngữ thú vị và thực dụng hơn rất nhiều so với kỳ vọng
    • Tác giả nói cảm giác này giống như lần đầu tiên tiếp xúc với Clojure trước đây
    • Đặc biệt nhớ lại việc Clojure từng là Lisp thực dụng nhất nhờ khả năng tương tác xuất sắc với Java
  • Nếu ngay từ đầu .NET đã là mã nguồn mở và portable,
    • ClojureCLR có thể đã phổ biến hơn hiện tại
    • cộng đồng cùng hệ sinh thái F# cũng có thể đã phát triển mạnh hơn
  • Việc F# không phải mã nguồn mở cho đến năm 2010 cũng đã cản trở việc được chấp nhận trong giai đoạn đầu

".NET và F# đều không phải mã nguồn mở trong giai đoạn đầu là sai lầm lớn nhất, và điều đó đã khiến nhiều cơ hội bị bỏ lỡ" – Don Syme

  • OCaml cũng không khó học, nhưng với người lần đầu học ngôn ngữ họ ML thì F# có thể dễ hơn
    • Rào cản để đi đến production cũng thấp hơn
  • Tác giả đặc biệt nhấn mạnh rằng nếu bạn đã có kinh nghiệm với .NET thì rất đáng để nhất định thử F#
    • F# không chỉ là một ngôn ngữ tuyệt vời theo đúng nghĩa độc lập, mà còn mở ra cơ hội tận dụng hệ sinh thái mạnh mẽ của .NET
  • Thông qua các công cụ như Fable, có thể transpile mã F# sang JavaScript, Dart, Rust, Python...
  • Trong cộng đồng F# có câu nói rằng "chữ F trong F# là Fun"
    • Sau khi tự tay dùng thử, tác giả cũng thấy câu này là thật, và nhấn mạnh rằng nó không chỉ vui mà còn thực dụng
  • Cuối cùng, bài viết cũng nhắc đến độ ổn định và độ tin cậy của F# qua câu "nếu biên dịch thành công thì phần lớn mọi thứ sẽ chạy tốt"

In sane type systems we trust!

1 bình luận

 
GN⁺ 2025-04-03
Ý kiến Hacker News
  • F# là ngôn ngữ hàm tốt nhất khi viết lại một ứng dụng Ruby on Rails

    • Đã cân nhắc Haskell, Ocaml, Scala và F#
    • Dù không quen với công nghệ của Microsoft, F# vẫn trở thành lựa chọn số một
    • Haskell khó được chấp nhận vì tính thuần túy của nó, còn hệ sinh thái của Ocaml thì thiếu thốn
    • Scala trông có vẻ phức tạp
    • F# dễ bắt đầu, và cộng đồng thì thân thiện, thông minh, luôn sẵn sàng giúp đỡ
    • Có một hệ sinh thái tuyệt vời với khả năng truy cập các thư viện dotnet
    • Có các thư viện và framework rất tốt như FsHttp giúp tương tác dễ dàng với máy chủ http
    • WebSharper là framework web tốt nhất trong toàn bộ các hệ sinh thái
    • Công cụ chưa ở trạng thái tốt nhất, nhưng có nhiều đam mê dành cho ngôn ngữ này
  • Đã thử F# nhưng còn mới với hệ sinh thái .NET

    • Bất ngờ vì có quá nhiều file dự án và mã khung được tạo ra chỉ để làm "hello world"
    • Ủng hộ FP, tính bất biến và ngôn ngữ hiện đại, nhưng công việc thì quá ít
    • Có xu hướng thích những ngôn ngữ dễ dùng với AI
    • Ở Ấn Độ tình hình còn tệ hơn, nhưng tại EU vẫn có thể sống ổn với Java/TypeScript
    • Khó tìm được công việc lương cao với Kotlin + TypeScript
  • Công ty chúng tôi đã chuyển từ C# sang F# cách đây 6 năm

    • Việc chuyển từ ngôn ngữ kiểu C khá khó, nhưng xứng đáng
    • Tốc độ biên dịch chậm và không hỗ trợ hot reload
    • Hiếm khi có cơ hội dùng nó trong công việc chuyên nghiệp
    • Việc tuyển dụng lập trình viên có thể khó khăn
  • Lý do việc tiếp nhận F# bị đình trệ là do hệ thống build kém

    • Rust là một ngôn ngữ tuyệt vời nhưng không phù hợp với nhiều miền bài toán
    • Lý do chọn Rust là vì hệ thống build của nó
    • Những ngôn ngữ có quỹ phi lợi nhuận và được nhiều công ty hỗ trợ vẫn có hệ thống build tệ
  • Đã học F# vào năm 2013 và thấy rất vui

    • Trải nghiệm người dùng không tốt
    • Có vấn đề với quy ước đặt tên, kiểu gọi hàm, cú pháp mặc định, tính năng của hệ thống kiểu và hỗ trợ IDE
    • Đã chuyển sang Scala và cảm thấy nó nhất quán hơn F#
    • F# là ngôn ngữ hàm đầu tiên và đã thay đổi góc nhìn về lập trình
  • F# là một trường hợp hiếm khi mọi người dùng đều rất hài lòng

    • Vì đã quen với hệ sinh thái .NET nên có vẻ sẽ dễ học
    • Tò mò không biết quy trình làm việc nào sẽ nhận được lợi ích lớn nhất
  • Khi C# có được nhiều tính năng của F#, lợi thế của F# đang giảm dần

    • Chủ yếu viết mã C# theo phong cách hàm, nhưng có lợi thế là có thể dùng thư viện theo đúng cách vốn có của chúng
  • Có một SaaS có lãi được viết hoàn toàn bằng F#

    • 3dpack.ing
    • Một trình ray tracer Rust viết bằng F# được biên dịch sang WebAssembly
    • fable-raytracer
  • F# là một ngôn ngữ tuyệt vời

    • Ngay cả khi không viết lấy một dòng, nó vẫn là một ngôn ngữ mẫu mực
    • Thường xuyên tham khảo fsharpforfunandprofit.com
  • F# đẹp nhưng khó dùng một cách thành thạo

    • Chỉ biết một ít C#, nên khó hiểu cách làm hướng đối tượng trong F#
    • Cũng gặp vấn đề tương tự với Clojure và Scala
    • Không muốn phải học C# hay Java trước