URL: https://linuxfr.org/news/ocaml-en-2021 Title: OCaml en 2021 Authors: octachron Yves Bourguignon, chimrod, Ysabeau đ§¶, Snark, BenoĂźt Sibaud, Anonyme, Bruno Ethvignot, Quidam, syntaxerror, MichaĂ«l, dourouc05 et tisaac Date: 2021ćčŽ01æ12æ„T16:25:31+01:00 License: CC By-SA Tags: ocaml Score: 58 La version 4.13.0 du langage OCaml est sortie le 24 septembre 2021, sept mois aprĂšs OCaml 4.12.0 sortie le 24 fĂ©vrier 2021. OCaml est un langage fonctionnel de la [famille des langages ML](https://fr.wikipedia.org/wiki/ML_(langage)) (dont font partie SML et F#). Il sâagit dâun langage fonctionnel multiâparadigme fortement typĂ© qui permet de mĂ©langer librement les trois paradigmes : fonctionnel, impĂ©ratif et objet. La plus grande spĂ©cificitĂ© dâOCaml dans le paysage des langages fonctionnels (Haskell, Rust, F#...) est probablement son systĂšme de module : les modules dâOCaml font partie intĂ©grante du langage, et il est par exemple possible de dĂ©crire des modules paramĂ©trĂ©s par dâautres modules (Ă travers des [foncteurs](https://ocaml.org/manual/moduleexamples.html#s%3Afunctors)). La grande nouveautĂ© de cette annĂ©e 2021 est la convergence de lâenvironnement dâexĂ©cution entre la version standard dâOCaml et le prototype dâOCaml multi-cĆur. Cette convergence amorce une nouvelle Ă©tape dans la transition vers OCaml multi-cĆur. Au-delĂ des progrĂšs vers OCaml multi-cĆur, cette annĂ©e 2021 a vu une de nombreuses avancĂ©es pour le langage OCaml et son compilateur que ce soit en termes dâarchitectures supportĂ©es, de messages dâerreurs, de fonctionnalitĂ©s du systĂšme de types, mais aussi des amĂ©liorations de confort pour les programmeurs que ce soit au niveau des outils de profilage, de la gestion des avertissements ou de la bibliothĂšque standard. ---- [Site officiel](https://ocaml.org) [Manuel de rĂ©fĂ©rence d'OCaml](https://ocaml.org/manual) [ocamlverse](https://ocamlverse.github.io/) [Forum officiel](https://discuss.ocaml.org/) [Changelog](https://github.com/ocaml/ocaml/blob/4.13/Changes) ---- # La route vers le multi-cĆur et OCaml 5.0 Une des limites de lâimplĂ©mentation actuelle de lâenvironnement dâexĂ©cution dâOCaml est son utilisation dâun verrou global. Ce verrou empĂȘche les applications _multithreads_ de bĂ©nĂ©ficier du parallĂ©lisme des fils dâexĂ©cution (_threads_). Au cours du temps, il y a eu plusieurs tentatives dâenlever ce verrou. La derniĂšre initiative a germĂ© chez OCaml Labs vers 2014-2015. Pour Ă©viter les Ă©checs prĂ©cĂ©dents, cette initiative a dĂ©cidĂ© de se concentrer sur deux points : une compatibilitĂ© descendante presque parfaite avec la version monocĆur dâOCaml, et une intĂ©gration incrĂ©mentale dans la branche principale dâOCaml. Ce travail de fond a commencĂ© Ă ĂȘtre visible dans OCaml 4.10.0. Mais il sâest notablement accĂ©lĂ©rĂ© dans OCaml 4.12.0. Une grande partie du travail dans OCaml 4.12 et 4.13 a Ă©tĂ© consacrĂ©e Ă diminuer les divergences entre lâenvironnement dâOCaml multi-cĆur et la version principale dâOCaml. Par exemple, un des changements majeurs prĂ©vus pour OCaml multi-cĆur est la gestion des pointeurs pointant en dehors de la mĂ©moire gĂ©rĂ©e par OCaml, sans ĂȘtre gardĂ©s par des mĂ©tadonnĂ©es (parce que, par exemple, ils ont Ă©tĂ© allouĂ©s par une bibliothĂšque C externe). Dans la version monocĆur dâOCaml, ces pointeurs Ă©taient gĂ©rĂ©s en gardant une trace des zones mĂ©moires allouĂ©es par OCaml. En passant Ă un environnement dâexĂ©cution multi-cĆur, cette stratĂ©gie devient prohibitive en coĂ»t de synchronisation. Ces pointeurs nus ne seront donc pas autorisĂ©s dans OCaml multi-cĆur. Pour assurer une Ă©volution en douceur, OCaml 4.12.0 a ajoutĂ© deux options de configuration : une option pour dĂ©sactiver la gestion des pointeurs nus directement pour les audacieux ; et une version plus prudente qui rajoute un test dynamique de la prĂ©sence de ces pointeurs nus. Cette derniĂšre option est notamment utilisĂ©e pour tester toutes les bibliothĂšques et programmes disponibles sur Opam (le dĂ©pĂŽt de paquets dâOCaml). Un autre point important est la gestion de lâordonnancement entre lâutilisateur et lâenvironnement dâexĂ©cution (_runtime_). Dans la version monocĆur dâOCaml, lâenvironnement dâexĂ©cution reprend la main Ă chaque allocation. Cela lui donne lâoccasion de vĂ©rifier si le Glaneur de Cellules (GC) Ă du travail Ă faire, ou sâil faut sâoccuper de signaux en attente. Une consĂ©quence est quâil est possible dâĂ©crire du code numĂ©rique qui nâalloue jamais et ne rend jamais la main Ă lâenvironnement dâexĂ©cution. En absence de parallĂ©lisme, ce comportement est plus une curiositĂ© quâautre chose. Mais pour multi-cĆur OCaml, ce comportement Ă©goĂŻste nâest plus de mise. Dans sa conception actuelle, OCaml multi-cĆur a une phase de GC en parallĂšle, pendant laquelle tous les fils dâexĂ©cution exĂ©cutent une passe de GC de maniĂšre synchrone. Il nâest donc pas question quâun fil dâexĂ©cution bloque le GC de tous les autres fils. Le compilateur natif a donc Ă©tĂ© modifiĂ© dans OCaml 4.13.0 pour sâassurer quâun fil dâexĂ©cution passe toujours la main Ă lâenvironnement dâexĂ©cution dans un temps bornĂ©. Un Ă©lĂ©ment qui commence Ă apparaĂźtre dans les discussions sur OCaml multi-cĆur est que lâon se rapproche dâun point oĂč il ne reste plus quâĂ faire le grand saut et intĂ©grer le _runtime_ multi-cĆur, et absorber les petites pertes de performances inĂ©vitables pour le code sĂ©quentiel. La premiĂšre version dâOCaml qui intĂ©grera la prise en charge du multi-cĆur sera OCaml 5.0. Cette nouvelle majeure commencera avec une pĂ©riode de transition durant laquelle la branche 4 sera maintenue activement. Cette premiĂšre version dâOCaml multi-cĆur nâintĂšgrera pas la partie la plus innovante de la proposition initiale, le systĂšme dâeffet, et se contentera dâexposer une bibliothĂšque de domaines et quelques API de plus haut niveau, bĂątis au-dessus de cette bibliothĂšque de domaine. Le but est de dĂ©coupler la partie _runtime_ du dĂ©veloppement dâOCaml multi-cĆur du travail de conception sur le systĂšme dâeffet qui requiert encore des efforts de conception. # Une prise en charge Ă©tendue de RISC-V Ă macOS/ARM64 Le compilateur OCaml gĂšre deux modes de compilation : un mode _bytecode_ qui fonctionne sur toute architecture oĂč un compilateur C est disponible ; et un mode natif qui Ă©met directement des binaires natifs. Ce mode natif est dâailleurs le seul utilisateur du systĂšme objet dâOCaml au sein du compilateur lui-mĂȘme. Cette gestion native requiert de sâadapter aux nouvelles familles de processeurs et aux variations dâABI suivant les systĂšmes dâexploitation. OCaml 4.11.0 a ainsi vu apparaĂźtre la prise en charge du RISC-V sous Linux. De maniĂšre similaire, la prise en charge prĂ©-existante pour ARM64 a Ă©tĂ© Ă©tendue pour couvrir les conventions dâappels de macOS dans OCaml 4.12.0 . # De meilleurs messages dâerreurs Ăcrire des messages dâerreurs utiles est une tĂąche plus difficile quâil nây paraĂźt. Il peut ĂȘtre tentant de communiquer une erreur interne sur lâimplĂ©mentation ou dâĂ©voquer une thĂ©orie avec laquelle lâutilisateur nâest pas familier. Un autre problĂšme assez frĂ©quent pour les erreurs de types dans OCaml est que le vĂ©rificateur de type est optimisĂ© pour vĂ©rifier rapidement que le code est bien typĂ©. Avec ce mode de fonctionnement, on ne dĂ©couvre parfois une erreur uniquement aprĂšs quâune sĂ©rie de petites erreurs nous ait menĂ© Ă une situation impossible. En bref, il reste pas mal de travail Ă faire pour amĂ©liorer les messages dâerreurs dâOCaml. Mais cette annĂ©e 2021 a vu quelques progrĂšs intĂ©ressants, et dâautres sont dĂ©jĂ intĂ©grĂ©s ou en cours dâintĂ©gration dans la version de dĂ©veloppement dâOCaml. ## Des messages dâerreurs plus dĂ©taillĂ©s pour les foncteurs Les foncteurs sont des fonctionnalitĂ©s uniques dâOCaml. Ils permettent de dĂ©crire des modules qui dĂ©pendent dâautres modules. Par exemple, la dĂ©finition dâun module `Graphe` peut prendre comme argument un module `Sommet` et un module `Arete` : ```ocaml module Graphe(Sommet:SOMMET)(Arete:ARETE) = struct ... end ``` Je peux ensuite instancier ce foncteur avec diverses implĂ©mentations de `ARETE` et `SOMMET`. Par exemple : ```ocaml module Graphe_basique = Graphe(Sommet_basique)(Arete_basique) module Graphe_colore = Graphe(Sommet_colore)(Arete_basique) ``` Cette formulation en termes de foncteur permet de dĂ©crire des algorithmes de graphes indĂ©pendamment de lâimplĂ©mentation des arĂȘtes ou sommets (sont-ils nommĂ©s ? colorĂ©s ?). Avant OCaml 4.13, les erreurs liĂ©es Ă ces foncteurs pouvaient ĂȘtre trĂšs verbeuses. Par exemple, si jâapplique le foncteur `Graphe` avec un argument en trop : ```ocaml module G = Graphe(Etiquette)(Sommet)(Arete) ``` Le vĂ©rificateur de type dâOCaml se plaignait que le module Etiquette nâest pas un `SOMMET`, ce qui donne un message dâerreur qui ressemble Ă cela : ``` Modules do not match: sig type t = string end is not included in SOMMET The value `label' is required but not provided The value `create' is required but not provided The type `label' is required but not provided The value `equal' is required but not provided The value `hash' is required but not provided The value `compare' is required but not provided ``` Avec OCaml 4.13.0, le vĂ©rificateur de type prend de la hauteur et essaye dâidentifier des erreurs de haut niveau dans les erreurs liĂ©es aux foncteurs : est-ce que lâutilisateur nâaurait pas oubliĂ© un argument ? AjoutĂ© un argument ? ModifiĂ© quelques arguments ? ``` Error: The functor application is ill-typed. These arguments: Etiquette Sommet Arete do not match these parameters: functor (Sommet : SOMMET)(Arete : ARETE)} -> 1. The following extra argument is provided Etiquette : sig type t = string end 2. Module Sommet matches the expected module type SOMMET 3. Module Arete matches the expected module type ARETE ``` De plus en utilisant des mĂ©thodes de _diffing_ (comparaison, gĂ©nĂ©ralement utilisĂ©es dans les correcteurs orthographiques ou du _fuzzy searching_/recherche floue), le vĂ©rificateur de type est capable de trouver une erreur la plus probable mĂȘme dans des cas complexes. ## Confusion entre module et module types Un des dĂ©tails surprenants dâOCaml est que beaucoup dâobjets ont leur espace de noms sĂ©parĂ©, ce qui mĂšne parfois Ă des erreurs entĂȘtantes. Par exemple : ```ocaml module type M = sig type t end type u = M.t ```> Error: Unbound module M ce message en OCaml 4.10.0 semble sâobstiner Ă ne pas reconnaĂźtre lâexistence de `M`. Le vĂ©ritable problĂšme est que `M` nâest pas un module, et donc ne dĂ©finit pas de types. Depuis la version 4.12.0, le message dâerreur reconnaĂźt quâil sâagit dâune confusion naturelle :> Error: Unbound module M Hint: There is a module type named M, but module types are not modules ## Une explication des problĂšmes de rĂ©gularitĂ© Parfois, les messages dâerreurs sont Ă©vidents pour leurs auteurs, et totalement obscurs sans le bon contexte. CâĂ©tait notamment le cas dâun des messages dâerreurs concernant les types rĂ©cursifs non-rĂ©guliers. Si lâenchaĂźnement des mots prĂ©cĂ©dents ne vous parle pas, il y avait de grandes chances que ce message dâerreur vous laisse pantois : ```ocaml type ('a,'b) x = [ `X of ('b,'a) y ] and ('a,'b) y = [ `Y of ('a,'b) x ] ```> Error: In the definition of y, type ('b, 'a) x should be ('a, 'b) x Il commet en effet trois pĂ©chĂ©s cardinaux pour un message dâerreur : il propose un correctif faux, il ne parle pas du code visible par lâutilisateur mais du rĂ©sultat dâun calcul invisible du compilateur, et il ne pointe pas vers la source de lâerreur. Ce souci est corrigĂ©, et OCaml 4.12.0 prend dĂ©sormais le temps dâexpliquer le problĂšme :> Error: This recursive type is not regular. The type constructor x is defined as type ('a, 'b) x but it is used as ('b, 'a) x after the following expansion(s): ('b, 'a) y = [ `Y of ('b, 'a) x ] All uses need to match the definition for the recursive type to be regular. Le message dâerreur est long. Cependant il explique non seulement la nature du problĂšme (un type paramĂ©trĂ© est utilisĂ© de façon diffĂ©rente au sein dâun mĂȘme groupe de dĂ©finition rĂ©cursif) mais aussi comment le vĂ©rificateur de type a dĂ©couvert lâerreur. # AmĂ©liorations de lâexpĂ©rience utilisateur Il y a aussi beaucoup dâamĂ©liorations de taille plus modeste qui sont plus difficiles Ă catĂ©goriser. Parmi celles qui ont retenu mon attention sur ces deux derniĂšres versions, je peux citer : ## Statmemprof : profiler la mĂ©moire sur des programmes en production. Pour des langages Ă glaneur de cellules (GC) comme OCaml, lâallocation et la dĂ©sallocation de mĂ©moire est un axe Ă la fois important et assez invisible de la performance des programmes. Il peut donc ĂȘtre important de surveiller le travail du GC dans un programme pour Ă©valuer des problĂšmes de performances, ou sâassurer quâil nây ait pas de fuite de mĂ©moire dans un serveur tournant durant des annĂ©es. Dans les versions dâOCaml antĂ©rieures Ă 4.12, la bibliothĂšque Spacetime fournissait de tels outils de surveillance en continu de la mĂ©moire. Cependant analyser le travail du GC peut-ĂȘtre extrĂȘmement coĂ»teux aussi bien en termes de temps que dâespace. Et il Ă©tait pratiquement impossible dâutiliser Spacetime dans un environnement de production Ă cause de ces coĂ»ts. Statmemprof est une rĂ©ponse Ă ces problĂ©matiques : il sâagit dâun outil de profilage statistique de lâallocation et de la dĂ©sallocation de la mĂ©moire. En sâautorisant Ă nâanalyser quâune partie des allocations et des dĂ©sallocations, il devient possible de contrĂŽler le coĂ»t de cette analyse de la mĂ©moire et de la rendre nĂ©gligeable. IntĂ©grer cette analyse dans du code en production devient alors possible. On peut mĂȘme sâautoriser Ă ajuster le comportement du programme en fonction de sa consommation mĂ©moire actuelle. ## Des noms pour les warnings AprĂšs 25 ans dâexistence, OCaml a accumulĂ© plusieurs dizaines dâavertissements (70 dans la version 4.13.0). Fort heureusement, la configuration de ces avertissements est souvent laissĂ©e soit au compilateur soit au systĂšme dâassemblage. Notamment, `dune`, le systĂšme dâassemblage de prĂ©dilection de la plupart des paquets opam, a un choix dâavertissements assez strict par dĂ©faut. Il reste nĂ©anmoins pratique de pouvoir modifier cette configuration pour un fichier ou une fonction spĂ©cifique. Par exemple, on peut activer le warning `27` pour juste la fonction `f` avec : ```ocaml let f x = () [@@warning "+27"] ``` Cependant, Ă la lecture, il nâest pas exactement Ă©vident de se rappeler lâobjet de cet avertissement `27`. Cela dâautant plus lorsque lâavertissement est utilisĂ© ponctuellement. La nouvelle mouture dâOCaml permet enfin de nommer ces avertissements : ```ocaml let f x = () [@@warning "+unused-var-strict"] ``` ## Et la Stdlib sâagrandit La bibliothĂšque standard voit arriver deux nouveaux modules liĂ©s aux threads : - `Atomic` : ce module est lĂ pour prĂ©parer en douceur la compatibilitĂ© avec le _runtime_ multi-cĆur. - `Thread.Semaphore` : ce module offre une contrepartie au `Mutex` qui nâa pas besoin dâĂȘtre verrouillĂ© et dĂ©verrouillĂ© dans le mĂȘme fil dâexĂ©cution. et un nouveau module de structure de donnĂ©es : - `Either` : il sâagit dâun module dâalternative gĂ©nĂ©rique (on a soit un `Left a` soit un `Right b`) qui est utile lorsque nommer explicitement les deux alternatives serait pĂ©nible. Fut un temps, la bibliothĂšque standard dâOCaml avait pour objectif de rester assez minimaliste. Ce choix a engendrĂ© la crĂ©ation dâau moins quatre bibliothĂšques Ă©tendant la bibliothĂšque standard (extlib, batteries, base, containers). Cependant depuis, OCaml 4.07 la bibliothĂšque standard sâest ouverte Ă plus dâamĂ©liorations. NĂ©anmoins, lâĂ©volution de la bibliothĂšque standard reste basĂ©e sur un principe de quasi-unanimitĂ©, son rythme dâĂ©volution reste donc trĂšs mesurĂ©. ## Des piles dâappels plus expressives Lorsque quâune fonction lĂšve une exception qui nâest pas attrapĂ©e, la pile dâappel (_backtrace_) contient dĂ©sormais des informations sur les noms des fonctions qui se sont retrouvĂ©es sur la pile dâappel. Par exemple exĂ©cuter : ```ocaml let () = let f () = let g () = raise Exit in fun () -> g () in f () () ``` nous informe que > Raised at Backtrace_example.f.g in file "backtrace_example.ml" (inlined), line 3, characters 16-26 plutĂŽt que le laconique > Raised at file "backtrace_example.ml" (inlined), line 3, characters 16-26 # Plus de types pour les utilisateurs experts Le systĂšme sâest aussi enrichi de fonctionnalitĂ©s plus orientĂ©es vers les auteurs de bibliothĂšques, et les utilisateurs experts. ## Des noms pour les types existentiels Les types existentiels sont une des fonctionnalitĂ©s nouvelles apportĂ©es par les Types de DonnĂ©es AlgĂ©briques GĂ©nĂ©ralisĂ©s (GADTs). Pour faire simple, il sâagit de types qui nâexistent quâĂ lâintĂ©rieur dâun constructeur. Par exemple, je peux dĂ©crire une pipeline de transformation de `'a` vers `b` en plusieurs Ă©tapes : ```ocaml type ('entree,'sortie) pipeline = | Vide: ('entree,'entree) pipeline | Etape: ('entree,'intermediaire) pipeline * ('intermediaire -> 'sortie) -> ('entree,'sortie) pipeline ``` Ici le constructeur `Etape` prend comme argument un pipeline de `entree` vers un type `intermediaire`, et une fonction de ce type `intermediaire` vers le type `sortie` et me donne en retour un pipeline de lâentrĂ©e vers la sortie. Le point intĂ©ressant avec dĂ©finition est que ce type intermĂ©diaire nâest pas un type concret connu. Il sâagit dâun type inconnu dont je sais seulement quâil est partagĂ© par ma pipeline interne, et ma fonction de transformation. Une bonne façon de voir comment ce type se comporte est dâimplĂ©menter une fonction `envoyer` qui applique toutes les Ă©tapes de la pipeline Ă une entrĂ©e et obtient une sortie. ```ocaml let rec envoyer: type entree sortie. (entree,sortie) pipeline -> entree -> sortie = fun pipeline entree -> match pipeline with | Vide -> entree | Etape(pipeline_interne, transformation_finale) -> entree |> envoyer pipeline_interne |> transformation_finale (* [x |> f] signifie [f x] *) ``` Ici, tout ce passe bien. Mais que se passe-t-il si jâessaye dâappliquer la transformation finale avant le reste de la pipeline ? ```ocaml let rec envoyer_erronee: type entree sortie. (entree,sortie) pipeline -> entree -> sortie = fun pipeline entree -> match pipeline with | Vide -> entree | Etape(pipeline_interne, transformation_finale) -> entree |> transformation_finale |> envoyer pipeline_interne ``` Jâobtiens une erreur de compilation qui se plaint que le type de `entree` nâest pas le bon :> Error: This expression has type entree but an expression was expected of type> $Etape_'intermediaire Et en effet, le code est faux parce que le type `entree` ne correspond pas au type attendu par la transformation finale. Le nom du type attendu `$Etape_'intermediaire` est cependant assez complexe. Il sâagit dâun nom automatiquement gĂ©nĂ©rĂ© pour un type existentiel Ă partir de la dĂ©finition de type et du constructeur qui lâa introduit. Ici le nom est assez clair, mais dans des cas complexes ces noms gĂ©nĂ©rĂ©s automatiquement peuvent ĂȘtre [difficiles Ă dĂ©chiffrer](https://ocaml.org/releases/4.12/manual/gadts.html#p:existential-names). Une des nouveautĂ©s dans 4.13.0 est quâil est dĂ©sormais possible de nommer soi-mĂȘme les types existentiels introduits dans le filtrage de motif: ```ocaml let rec envoyer_erronee: type entree sortie. (entree,sortie) pipeline -> entree -> sortie = fun pipeline entree -> match pipeline with | Vide -> entree | Etape (type intermediaire) (pipeline_interne, transformation_finale: (entree, intermediaire) pipeline * (intermediaire -> sortie) ) -> entree |> transformation_finale |> envoyer pipeline_interne ``` Cette fois-ci, le message dâerreur utilise notre nom de type :> Error: This expression has type entree but an expression was expected of type> intermediaire Ce qui devrait rĂ©duire lĂ©gĂšrement le temps passĂ© Ă faire compiler du code utilisant fortement les [GADT](https://en.wikipedia.org/wiki/Generalized_algebraic_data_type). Cette notation permet aussi dâobtenir facilement le type abstrait correspondant au type existentiel pour lequel il y a des applications plus Ă©laborĂ©es. ## De lâinjectivitĂ© pour vos types Les bibliothĂšques vont pouvoir ajouter des points dâexclamation Ă leurs types ```ocaml type !'a vec ``` pour indiquer que le paramĂštre `'a` est vraiment utilisĂ© dans le type et nâest pas un type fantĂŽme. Cela permet de dĂ©bloquer certains usages avancĂ©s des GADT oĂč il est vital de savoir si `int vec` et forcĂ©ment diffĂ©rent de `float vec`. Par exemple, avec cette annotation, le vĂ©rificateur de type sait quâavec la dĂ©finition suivante : ```ocaml type _ int_or_float_vec = | Int_vec : int vec -> int vec int_or_float_vec | Float_vec: float vec -> float vec int_or_float_vec ``` lorsquâon a une valeur de type `'a int_or_float_vec`, la variable `'a` est forcĂ©ment soit `int vec` soit `float vec`. En dâautres mots, on ne peut jamais se procurer une valeur de type `char int_or_float_vec` : ```ocaml let impossible: char int_or_float_vec -> _ = function _ -> . ``` Sans cette annotation, le vĂ©rificateur de type ne peut Ă©liminer la possibilitĂ© que le type `'a vec` ait Ă©tĂ© dĂ©fini en tant que synonyme de `char`: ```ocaml type 'a vec = char ``` Comme pour les annotations de variances, lâinjectivitĂ© est automatiquement infĂ©rĂ©e pour les types non-abstraits. Ces annotations sont donc essentiellement lĂ pour les auteurs de bibliothĂšque. # Au-delĂ dâOCaml multi-cĆur Si lâimplĂ©mentation dâOCaml multi-cĆur se rapproche lentement mais inexorablement, les plans pour le futur dâOCaml ne sâarrĂȘtent pas lĂ . En particulier, la gestion de la concurrence et du parallĂ©lisme sera Ă terme basĂ©e sur un systĂšme dâeffets. La prochaine Ă©tape de ce cĂŽtĂ© sera de concevoir et dĂ©ployer un systĂšme dâeffets typĂ©s facile Ă utiliser en pratique. Mais le dĂ©veloppement dâOCaml 5 ne se concentrera pas uniquement sur lâaspect multi-cĆur. Une des forces dâOCaml est son systĂšme de modules Ă la fois expressif et adaptĂ© Ă la compilation sĂ©parĂ©e. Cependant, cette puissance a un prix, et les usages avancĂ©s du systĂšme de modules peuvent ĂȘtre particuliĂšrement lourds syntaxiquement. Un des projets en cours pour OCaml 5 est dâintroduire des mĂ©thodes plus lĂ©gĂšres pour dĂ©crire des fonctions paramĂ©trĂ©es par des modules, Ă travers un systĂšme de foncteurs lĂ©gers et implicites.