Introduction
F# est un langage fonctionnel de premier ordre sur la plateforme .NET qui combine la puissance de la programmation fonctionnelle avec l'écosystème Microsoft. En 2026, il excelle dans les domaines du data engineering, des services web et des applications concurrentes grâce à son système de types robuste et ses expressions de calcul. Ce tutoriel intermédiaire vous guide pas à pas pour construire une application console complète exploitant les discriminated unions, les computation expressions et les workflows async. Chaque concept est illustré par du code fonctionnel que vous pouvez exécuter immédiatement.
Prérequis
- .NET SDK 8.0 ou supérieur
- Visual Studio 2022 ou VS Code avec l'extension Ionide
- Connaissances de base en programmation fonctionnelle et TypeScript/C#
- Familiarité avec les concepts de pattern matching
Initialiser le projet F#
dotnet new console -lang F# -o FSharpTutorial
cd FSharpTutorial
dotnet runCette commande crée un projet console F# standard. Le fichier Program.fs contient déjà un point d'entrée main. Exécutez dotnet run pour vérifier que l'environnement fonctionne correctement.
Définir des discriminated unions
module Domain
type OrderStatus =
| Pending
| Shipped of DateTime
| Delivered of DateTime * string
let status = Shipped (DateTime.Now)
let describe status =
match status with
| Pending -> "En attente"
| Shipped date -> $"Expédié le {date}"
| Delivered (date, carrier) -> $"Livré par {carrier} le {date}"Les discriminated unions modélisent des états exhaustifs de manière sûre. Le pattern matching force le développeur à gérer tous les cas, évitant les erreurs runtime courantes en C#.
Utiliser les records immuables
module Models
type Order = {
Id: Guid
Customer: string
Amount: decimal
Status: Domain.OrderStatus
}
let createOrder customer amount =
{ Id = Guid.NewGuid()
Customer = customer
Amount = amount
Status = Domain.Pending }Les records F# sont immuables par défaut. Cela garantit la sécurité des données dans les applications concurrentes et facilite le raisonnement sur le code.
Implémenter un workflow async
module AsyncWorkflow
open System.Net.Http
open System.Threading.Tasks
let fetchDataAsync (url: string) =
async {
use client = new HttpClient()
let! response = client.GetStringAsync(url) |> Async.AwaitTask
return response
}
let runExample () =
fetchDataAsync "https://jsonplaceholder.typicode.com/todos/1"
|> Async.RunSynchronously
|> printfn "%s"Les workflows async en F# simplifient la programmation asynchrone sans callbacks. Le mot-clé async crée une computation expression qui gère automatiquement les continuations.
Créer une computation expression
module ResultBuilder
type ResultBuilder() =
member _.Bind(x, f) =
match x with
| Ok v -> f v
| Error e -> Error e
member _.Return(x) = Ok x
let result = ResultBuilder()
let validateOrder order =
result {
let! amount = if order.Amount > 0m then Ok order.Amount else Error "Montant invalide"
return { order with Amount = amount }
}Les computation expressions permettent de créer des DSL pour gérer les erreurs ou les états. Ici, le builder Result évite les if-else imbriqués et rend le code plus lisible.
Point d'entrée principal
open Domain
open Models
open AsyncWorkflow
open ResultBuilder
[<EntryPoint>]
let main argv =
let order = createOrder "Alice" 150.0m
printfn "%s" (describe order.Status)
let validated = validateOrder order
match validated with
| Ok o -> printfn "Commande valide: %A" o
| Error msg -> printfn "Erreur: %s" msg
runExample () |> ignore
0Le fichier Program.fs orchestre tous les modules précédents. Il démontre l'utilisation conjointe des discriminated unions, records et computation expressions dans un flux réel.
Bonnes pratiques
- Préférez toujours les types immuables pour les données métier
- Utilisez les discriminated unions pour modéliser les états exhaustifs
- Exploitez les computation expressions pour les opérations complexes (async, result, option)
- Écrivez des tests avec FsUnit ou Expecto dès le début
- Activez les avertissements du compilateur comme erreurs pour un code plus sûr
Erreurs courantes à éviter
- Oublier de gérer tous les cas dans un pattern matching (le compilateur vous avertit)
- Utiliser des types mutables dans du code concurrent
- Ignorer les performances des listes infinies avec Seq
- Mélanger du code F# et C# sans comprendre les conventions de nommage
Pour aller plus loin
Approfondissez les Type Providers et la métaprogrammation F# dans nos formations Learni.