Back to flin
flin

Le système de types de FLIN : inféré, expressif, sûr

Comment nous avons conçu le système de types de FLIN pour être inféré par défaut, expressif quand nécessaire et sûr au moment de la compilation -- sans la taxe de verbosité des langages typés traditionnels.

Juste A. Gnimavo (Thales) & Claude | March 26, 2026 5 min flin
EN/ FR/ ES
flintype-systeminferencesafety

La plupart des langages de programmation forcent un choix. Vous pouvez avoir la sécurité, mais vous la payez avec des annotations de type sur chaque ligne. Ou vous pouvez avoir la brièveté, mais vous acceptez que des catégories entières de bogues ne se manifestent qu'à l'exécution, en production, à 3 heures du matin.

FLIN refuse le compromis.

Quand nous nous sommes assis pour concevoir le système de types de FLIN -- un langage destiné aux développeurs qui veulent construire des applications full-stack dans un seul fichier -- nous avons commencé par une question qui semble simple mais porte d'énormes conséquences : quelle est la quantité minimale d'informations de type qu'un développeur devrait avoir à écrire, étant donné que le compilateur peut déterminer le reste ?

La réponse est devenue la fondation de tout dans cet article : des types que vous écrivez rarement, une sécurité que vous obtenez toujours.

Les principes de conception

Quatre principes ont guidé chaque décision du système de types.

Inféré. Les types sont automatiquement déterminés à partir des valeurs. Si vous écrivez count = 42, le compilateur sait que c'est un int. Vous ne devriez pas avoir à le lui dire.

Simple. Un petit ensemble de types clairs et utiles. Pas de distinction entre i8, i16, i32, i64, u8, u16, u32, u64 comme en Rust. Pas de String versus &str versus &'a str. Un type entier. Un type virgule flottante. Un type texte.

Sûr. Attraper les erreurs au moment de la compilation, pas à l'exécution. Si vous essayez d'additionner un nombre et une valeur texte, le compilateur devrait vous le dire immédiatement, pas laisser l'application planter quand un utilisateur déclenche ce chemin de code six mois plus tard.

Pratique. Des types qui correspondent aux données du monde réel. Un type money qui comprend les devises. Un type time avec des mots-clés temporels. Un type semantic text qui génère automatiquement des embeddings IA.

Types primitifs

FLIN a quatre types primitifs :

flinname = "Juste"          // text -- chaîne UTF-8
count = 42              // int -- entier signé 64 bits
price = 99.99           // number -- virgule flottante 64 bits
active = true           // bool -- booléen

Pas d'annotations de type. Le compilateur infère chacun. Le développeur écrit la valeur ; le compilateur détermine le type.

Types spéciaux

Time

Le type time est un horodatage UTC avec précision nanoseconde, avec des mots-clés temporels : now, today, yesterday, tomorrow, last_week, last_month. Ces mots-clés ne sont pas des fonctions. Ce sont des valeurs.

Money

Le type money impose l'homogénéité des devises. Deux valeurs money ne peuvent participer à l'arithmétique que si elles partagent une devise. C'est une contrainte qui nécessiterait une validation à l'exécution dans la plupart des langages mais devient une garantie au moment de la compilation dans FLIN.

Semantic Text

Un champ semantic text est automatiquement embarqué dans une représentation vectorielle quand il est sauvegardé. Cela active la recherche par similarité vectorielle sans que le développeur ne touche jamais un modèle d'embedding.

Inférence de types

L'inférence de types dans FLIN est bidirectionnelle. L'information coule des valeurs vers les variables (inférence avant) et du contexte vers les expressions (inférence arrière).

Chaque opération d'entité a un type de retour connu. Entity.all retourne [Entity]. Entity.find(id) retourne Entity? -- un optionnel. Entity.count retourne int. Le compilateur propage ces types à travers chaque opération suivante sur le résultat.

Types optionnels

Tout type peut être rendu optionnel avec ?. FLIN élimine les exceptions de pointeur nul grâce à la propagation automatique de none et au rétrécissement de type :

flinuser: User? = User.find(id)
if user {
    // À l'intérieur de ce bloc : user est User (pas User?)
    print(user.name)    // sûr -- le compilateur sait que user n'est pas none
}

Messages d'erreur

Un système de types n'est aussi bon que ses messages d'erreur :

error[E0001]: type mismatch
  --> app.flin:12:15
   |
12 |     count = "hello"
   |             ^^^^^^^ expected int, found text
   |
   = note: count was declared as int on line 5
   = hint: use int("hello") to parse, or change count's type

Chaque message d'erreur a trois parties : ce qui s'est mal passé, où c'a été déclaré et quoi faire. L'indice suggère des corrections concrètes.

L'implémentation en Rust

Le système de types entier est implémenté en environ 4 000 lignes de Rust à travers trois fichiers. Le FlinType enum est la structure de données centrale avec des variantes pour Int, Number, Text, Bool, Time, Money, List, Map, Optional, Entity, Union, TypeParam, Generic, Enum, Never, Any et Unknown.


Ceci est la partie 31 de la série « Comment nous avons construit FLIN », documentant comment un CEO à Abidjan et un CTO IA ont conçu et implémenté un langage de programmation à partir de zéro.

Navigation de la série : - [31] Le système de types de FLIN : inféré, expressif, sûr (vous êtes ici) - [32] Types union et rétrécissement de type - [33] Types génériques dans FLIN - [34] Traits et interfaces - [35] Pattern matching : de switch à match

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles

Thales & Claude thales

Treize agents, quarante-trois minutes : la première session Workflow de Claude Fable 5, et ce qu'un script d'orchestration déterministe change aux builds multi-agents

Un prompt, treize agents, quarante-trois minutes : la première session de production avec Claude Fable 5 et l'outil Workflow de Claude Code a livré un site web de production complet de sept pages plus un endpoint backend de capture de leads, en un seul commit. Le carnet de bord : le script d'orchestration déterministe, le patron d'injection de contrat entre les phases, l'économie par agent du fan-out parallèle, et le suspense de la limite de session que le journal de reprise a transformé en non-événement.

23 min Jun 12, 2026
claude-fable-5claude-codeworkflow-toolmulti-agent +10
Thales & Claude casp

La porte a détecté sa propre dérive : une journée dans CASP avec Claude Fable 5

Nous avons confié au modèle Claude le plus autonome à ce jour les clés de CASP — le CLI open source qui garde les agents de code IA honnêtes face à git — avec l'autorité de rejeter notre propre roadmap. Il a rejeté cinq choses, trouvé deux vrais bugs dans le validateur en le dogfoodant, les a corrigés sous une porte à deux auditeurs, et a laissé casp check entièrement vert sur son propre dépôt pour la première fois. CASP 0.3.0 en est le résultat.

16 min Jun 10, 2026
caspzerosuiteworkflowai-cto +9
Thales & Claude zerosuite

La transplantation du CASP : comment la discipline des six fichiers est passée de Conductor à un ERP transport anti-fraude, ce que la compétence /next ajoute quand l'opérateur tape juste « next », et pourquoi le coût d'une dérive du CASP grimpe quand le projet, c'est l'argent des autres

La discipline du CASP qui a piloté trente-cinq sessions de Conductor est agnostique au produit. Le carnet de bord de sa transplantation sur KASSIA, un ERP transport anti-fraude pour un exploitant de flotte en Côte d'Ivoire : ce qui a migré, ce qui n'a pas migré (le validateur sur mesure — et ce que son absence coûte), ce que la compétence /next ajoute quand l'opérateur tape un seul mot, et là où le CASP s'arrête — le bug de déploiement qu'il ne pouvait pas voir parce qu'il enregistre l'intention, pas la réalité de l'infrastructure.

23 min Jun 8, 2026
kassiaerp-kassia-transport-logistiquezerosuiteCASP +15