Job F# vừa hiếm, vừa không có offer tốt ở HCM lẫn HN.
Dù học ngôn ngữ nào hay paradigm nào, cái mình nên học là ý tưởng để giải quyết vấn đề.
F# có những ảnh hưởng trực tiếp lẫn gián tiếp đến sự phát triển của C# cũng như các dự án và ngôn ngữ khác (Rx, TypeScript, Kotlin, Python 3.5, Java, JavaScript, Scala,...)[1]. Dưới đây là một vài ảnh hưởng trực tiếp:
- Generic (C# 2)
- Type inference (
var x = ...) (C# 3)
- async/await (C# 5). Asynchronous programming trong F# ra mắt từ nửa cuối 2007[2]; C# 5 ra mắt khoảng cuối 2011 cùng với VS 2012 và .NET Fx 4.5.
- Pattern matching (C# 7, 8, 9)
- Tuple (C# 7)
- Nullable reference type (C# 8, default in new project in C# 10, .NET 6)
- Record (C# 9)
- First-class events và compositional event-combinator programming[3] là niềm cảm hứng cho sự hình thành và phát triển của Rx project - reactive programming. Các bạn làm front-end thường biết đến RxJS.
- Discriminated union/Type union (C# language proposal)
Mình chỉ liệt kê số lượng, không so sánh chất lượng và những khác biệt. So sánh sẽ khập khiễng.
Ngược lại, C# cũng ảnh hưởng đến sự phát triển của F# (dưới góc độ ngôn ngữ); đồng thời F# cũng được hưởng lợi rất nhiều do nó là một phần trong hệ sinh thái .NET.
Mình biết rất ít về Python, nhưng có lẽ mình phần nào đồng tình với nhận xét về hệ sinh thái.
Domain modeling là cốt lõi của nhiều nghiệp vụ. Về mặt này, F# có lợi thế hơn C#. F# có discriminated union (DU) và units of measure mà C# thì không[4][5][6][7]. Trong khi với F#, người ta dùng DU để mô hình hoá (modeling) các lựa chọn; thì với C#, người ta dùng những công cụ như enum, inheritance với base/derived classes. Đứng từ góc độ một domain expert (non-technical people), đọc code F# dễ hiểu và dễ verify hơn type hierarchy bên C#.
Nếu bạn cho rằng OOP (C# nói riêng) là phương pháp tuyệt vời để làm domain modeling, hãy gạt thiên kiến đó qua một bên[8] để xem cách người ta làm với một functional language ra sao[9][10][11][12].
[1] Don Syme. 2020. The Early History of F#, page 49-51.
[2]
Introducing F# Asynchronous Workflows (https://learn.microsoft.com/en-us/archive/blogs/dsyme/introducing-f-asynchronous-workflows)
[3]
F# First Class Events: Simplicity and Compositionality in Imperative Reactive Programming (https://learn.microsoft.com/en-us/archive/blogs/dsyme/f-first-class-events-simplicity-and-compositionality-in-imperative-reactive-programming)
[4]
Champion "Discriminated Unions" · Issue #113 · dotnet/csharplang (https://github.com/dotnet/csharplang/issues/113)
[5]
csharplang/proposals/TypeUnions.md at 18a527bcc1f0bdaf542d8b9a189c50068615b439 · dotnet/csharplang (https://github.com/dotnet/csharplang/blob/18a527bcc1f0bdaf542d8b9a189c50068615b439/proposals/TypeUnions.md)
[6]
csharplang/proposals/discriminated-unions.md at 18a527bcc1f0bdaf542d8b9a189c50068615b439 · dotnet/csharplang (https://github.com/dotnet/csharplang/blob/18a527bcc1f0bdaf542d8b9a189c50068615b439/proposals/discriminated-unions.md)
[7]
GitHub - mcintyre321/OneOf: Easy to use F#-like ~discriminated~ unions for C# with exhaustive compile time matching (https://github.com/mcintyre321/OneOf)
[8]
Tách trà (https://trandinhhoanh.wordpress.com/2009/12/10/tach-tra/)
[9]
Low overhead type definitions | F# for fun and profit (https://fsharpforfunandprofit.com/posts/conciseness-type-definitions/)
[10]
The 'designing with types' series | F# for fun and profit (https://fsharpforfunandprofit.com/series/designing-with-types/)
[11]
Domain Driven Design | F# for fun and profit (https://fsharpforfunandprofit.com/ddd/)
[12]
Why type-first development matters (https://tomasp.net/blog/type-first-development.aspx/)