Précédent
Suivant

Genèse (2)

Réflexion préalable : Langage de programmation idéal
Post-reflexion : Le langage informatique hardware idéal

 

1) Le langage des types

L'étude des objets informatiques passe par l'étude de leur type, et par l'étude du langage des types qui trouve paradoxalement une partie de ses fondements dans le hardware.

Nous avons vu deux opérations fondamentales de construction de type que sont le produit `A"×"B`, le type des couples d'éléments, et `A"→"B`, le type des applications de `A` vers `B` qui lorsque elles sont définies par leur graphe se note plus précisement `B^A`.

Puis nous avons vu la puissance `A^n`, le type des `n`-uplet d'éléments de `A` qui correspond au type `{0 ".." n"-"1}->A`

Le symbole `"→"` est aussi utilisé pour construire les types pointeurs. Le type des pointeurs d'élément de `A` se note `"→"A`. Mais, s'ils pointent des éléments de `A` pouvant se trouver dans l'espace mémoire tout entier et calé sur le découpage par octet, alors on se restreint à une adresse en nombre entier d'octets selon les prédispositions de l'architecture matérielle, et leur type se note plus précisement `&A`. La taille mémoire d'un élément de type `&A` est égale à `log_(2^8)(M)` octets où `M` désigne la capacité totale de mémoire de l'ordinateur en nombre d'octets.

L'apport de l'architecture matérielle et de ses contraintes, loin de nous égarer dans des détails techniques, va au contraire nous procurer les fondements du langage des types, un fondement non-arbitraire. Voyons comment nous pouvons parfaire notre raisonnement, notre construction... telle une genèse non plus logique mais informatique dans l'élaboration du langage des types.

Il conviendra de commencer par le type le plus rudimentaire qu'est le type énumératif.... Et le premier des types énumératifs s'appelle le booléen, la valeur booléenne `0` ou `1`.

Mais avant même cela, ne pouvant rien écrire qui est du sense dans cette mémoire vive de l'ordinateur qui se présente comme une succession de bits sans qu'aucun type prédéfini ne disent ce que l'on peut faire avec, il convient de définir ce type, un type en toile de fond qui définit un langage background, ce qui reste lorsque l'on a tout enlevé. Et c'est le mariage entre ce langage qu'est le software et la structure matérielle qu'est le hardware qui va accoucher d'un langage de programmation solide. On procède alors comme un archéologue qui découvre des hiéroglyphes, ici très rudimentaires puisque composés d'une succession de `0` et de `1`, et on cherche à découvrir le langage qui est utilisé pour donner un sense à ces hiéroglyphes.

2) La structure de la mémoire

L'ordinateur contemporain comprend une mémoire vive qui se présente comme une suite de bits. Cette suite est subdivisé en bloc de huit bits appelé octet. Les octets sont numérotés de `0` à `N` et dans chaque octet les bits sont numérotés de `0` à `7`. Ce qui fait que l'adresse d'un bit est un couple de nombre dont le premier est l'addresse de l'octet et le second est l'adresse relative du bit dans l'octet.

Conventionellement les bits ou octets d'adresse plus élevée sont dits de poid fort, c'est-à-dire que s'ils fonts partie d'un même bloc de bits ou d'octets d'un seul tenant transportant une information, ils sont supposés avoir plus de poid, c'est-à-dire qu'ils sont supposés transporter une information ayant un impacte plus important.

Conventionellement, dans un transfert de bits, on commence par transmettre les bits de poid forts, de même dans un transfert d'octets, on commence par transmettre les octets de poid fort en premier, sans doute pour transmettre les informations majeures en premier.

Conventionellement on représente une transmission de bits en les écrivant de gauche à droite. C'est pourquoi conventionellement on représente graphiquement un bloc de bits de gauche à droite en partant du bits de poid le plus fort pour terminer par le bit de poid zéro.

(L'architecture peut mettre en oeuvre un boutisme différent. Cela n'a pas d'importance.)

2) Le langage de fond

Une subdivision en séquence de bits d'un seul tenant, appelé bloc ou objet, est rechercher par l'archéologue. La succession de bits que constitue la mémoire de l'ordinateur est déjà subdivisée en octets par l'architecture matérielle, et les objets à certains moments devront pour des raisons d'efficacité, se caler sur ces octets c'est à dire débuter à l'adresse de début d'un octet, et/ou se terminer à l'adresse de fin d'un octet, et/ou être d'une taille égale à un nombre entier d'octets. Mais, on ne doit pas se soumettre complètement à cette contrainte, car l'entropie des données joue un rôle clef en informatique. On doit pouvoir définir des types denses, voir complètement denses, c'est à dire où chaque objets de ce type correspond à un bloc de bits d'un seul tenant et où chaque configuration de bits correspond à un objet distinct de ce type.

Dans notre approche générale de cette mémoire linéique, notez qu'un type peut contenir des objets de tailles différentes. Cela a pour conséquence de classifier les types selon le mécanisme mis en oeuvre pour déterminer la taille de leurs objets. Il y a trois catégories d'objet :

Chaque type se range dans une des 3 catégories : type de modon, type de varon ou type de nonon. Le nonon semble ne pas servir à grand chose, mais en procédant ainsi, on est exhaustif, complet et exacte. Le concept qui reste ouvert et pour lequel on n'a pas donné de définition, c'est le type. Puis en passant en revue les techniques de programmation de bas niveau que nous rangerons dans différents niveau de protocoles, on précisera concrètement ce que l'on entend par la notion de type, et qui se déclinera pour chaque un niveau de protocole.

Le langage que nous voulons définir est polymorphe c'est-à-dire qu'il change de forme en cours de route pouvant ainsi toujours s'adapter au problème.

Puisque nous créons un langage qui s'adapte sur mesure pour chaque problème, il n'est plus à craindre de s'égarer dans l'élaboration d'un langage de fond spécifique épousant le hardware.

Mais ce langage devra constituer l'embryon de tous les autres langages. Nous procédons à sa conception en élaborant une axiomatique, en créant des objets, des types et des procédés généraux qui satisfont des axiomes, et dont l'empilement s'opère ainsi récurcivement selon une axiomatique.

La distinction entre les objets calés et ceux non-calés sur le découpage par octet de la mémoire devra être faite dès le départ pour des raisons d'efficacités. Pour cela on utilise 3 flags `"o"`, `"d"`, `"f"`, qui détermine cette qualité maintenue ou non :

Notez que :

Et que ces trois flags peuvent être remplacé par un indicateur à 5 états : `"odf", "o", "d", "f", "_"`.

Le modon se complète par la détemination de ces trois flags ou par cet indicateur à 5 états. Mais celui le plus courant sera `"odf"` noté `"modon"_"odf"`. Et cela s'applique à tous les types.

3) Les varons

Pour déterminer la taille des varons, il y a plusieurs mécanisme selon le niveau de protocole mis en oeuvre. Au bas niveau, le varon est un couple d'objet dont le premier objet est un modon ou un varon qui détermine la taille du second objet.

On limite cette construction en précisant que le premier objet ne transporte comme information uniquement la taille du second, c'est à dire un entier natuel. Cette restriction ne diminue en rien la capacité expressive du langage. En effet, si l'on souhaite ajouter au varon une donnée de taille fixe, un modon, on procède simplement à la concaténation du modon et du varon.

Un exemple fondamental de varon est donné par le caractère de norme UTF8. Cette norme détermine si le caractère tient sur 1, 2, 3 ou 4 octets selon une règle un peu tordu, mais que l'on va introduire dès le départ, car l'on souhaite utiliser cette norme universelle qu'est l'utf8/unicode dès la conception du noyaux de notre système. Néanmoins les choix qui ont été fait pour définir l'utf8 ne sont pas les bons. La conception logique aurait choisit comme norme pour déterminer la taille des caractères, une norme plus générale s'inscrivant dans une catégorie plus large de varon. Par exemple en choissisant un premier sous-objet de type baton pour déterminer le nombre d'octet du caractère.

Puis quelque soit le niveau de protocole, toute concaténation de modons et de varons, du momement qu'elle contient au moins un varon, est un varon. De même tout concaténation d'objet, du moment qu'elle contient un nonon, est un nonon.

4) Les tables

Au niveau de protocole suivant, on définit les tables c'est-à-dire des objets comprenant éventuellement un sous-objet de tête déterminant la taille, suivi par une succession de modons de même type.

4) Les chaines

Au niveau suivant, on définit les chaines c'est-à-dire des objets comprenant éventuellement un sous-objet de tête déterminant la taille, suivi par une succession d'objets de même type. Les chaines de modons étant des tables, il reste donc deux catégories de chaines, les chaine de varons et les chaines de nonons,

Le type de nonons s'apparente au type ensemble d'objets brutes. Un tel type peut être vu comme un ensemble d'objets brutes.

Les chaînes de nonons sont plus compliqués à traiter que les chaines de varons, car elles nécessitent de choisir un mécanisme pour déterminer la taille des nonons successifs dans la chaine.

Si on se restreint, dans l'interprétation de la chaine de nonons, à ne considérer dans l'ordre de lecture que les blocs de taille maximale correspondant à des nonons du type en question, alors on définit un nouveau type appelé chaine de mots. Le type de nonons considéré s'apparente alors à un dictionnaire. Ce dernier type sert d'interface proposant un langage de formules proche de celui de l'utilisateur. C'est pourquoi il n'est pas utilisé dans le noyaux du système, et qu'il est converti systématiquement en des objets à peine plus redondant, de type chaine de varons, où les mots sont transcrit en des varons, c'est à dire où les mots sont bien séparés les uns des autres.

Les chaines de mots sont des chaines-fix de mots ou des chaines-param de mots, et si le dictionnaire possède un mot de fin qui ne doit pas coïncider avec aucun début d'autre mot du dictionnaire, alors on peut également définir la chaine-fin de mots.

Pour des raisons d'efficacité, les blocs de taille fixe sont d'une taille  de `1` bits ou `2` bits ou `4` bits ou `8` bits ou `16` bits ou `24` bits ou `32` bits ou `48` bits ou `64` bits.

L'octet est une subdivision hardware qui est calé, tandis que le bloc est une subdivision software qui n'est pas nécessairement calé.

Grace aux chaines de mots, composé de caractères calés au format unicode/utf8. Ce peu-être des chaines de caractères (ou des chaines de chaines de varons calés), on définit un langage plus évolué, On définit un langage d'opérateurs lisible par un humain. Une phrase de ce langage est une chaine de caractères. Les suites de caractères forment des mots reconnus par un dictionnaire, les suites de mots forment des phrases reconnues par une grammaire.

C'est la naissance du langage dit d'opérateurs. Les objets (mots) s'emboitent les uns dans les autre à l'aide d'autres objects (mots) jouant le rôle d'opérateur pour former des objets plus comlexe appelés termes (phrase). Les objets (mots) s'appellent aussi des opérateurs. Les assemblages d'objets (mots) s'appellent des termes (phrase). Les termes de ce langage que constituent nos objects, sont des chaînes de caractères. Ils admettent une première représentation à peine plus redondante dans laquelle chaque mot est remplacé par une chaine, c'est-à-dire que chaque mot est séparé des autres mots. Puis ils admettent une seconde représentation sous forme d'arbres d'appel que l'on considère comme étant leur implémentation profonde. La transcription de l'arbre en la chaîne de mots et vis-versa s'opère grace à la syntaxe des opérateurs décrite dans la grammaire, définie dans le langage, déclarée dans le contexte en cours. Chaque contexte précise un langage en cours. Ainsi le langage peut toujours s'adapter au problème.

Le langage de fond est le langage qui reste une fois que l'on a tout enlevé. C'est le langage avant toute définition de langage. C'est-à-dire qu'après une première phase où le langage de fond est utilisé, d'autres langages seront définis et serviront de langage en cours, empilés dans les contextes.

C'est pourquoi le langage de fond se préoccupe fortement du hardware. Puis, il faut noter que l'empilement des langages ne nuit pas à l'efficacité car elle ne correspond pas à un empilement de couches logiciels. Et c'est dans cette esprit que l'on construit la notion de type.

3) La construction du langage de fond

Est-il possible de construire le langage de programmation par étape ? Et si c'est le cas, qu'elle est la première étape ? Les constantes, les variables, les fonctions, les types....

Rappellons que le recours au langage de fond se fait par l'intermédiaire de caractères calés au format UTF8, mais n'empêche pas d'intercaler des objects brutes non-calés qui obéissent, pour déterminer leur taille, au règles précédentes.

Ainsi, nous construisons dés le départ, un langage de programmation pouvant agire sur lui-même, qui est à la fois une donnée brute avec plusieur niveaux de langage, et qui peut agire sur des programmes comme sur des données.

3.1) Les chaînes de caractères

Les premières constantes auxquelles on pense, sont les chaînes de caractères, et on peut les déclarer grâce à l'usage de guillemet à condition qu'elle ne contiennent pas de guillemet.

Les variables, et les fonctions (opérateurs) sont identifiées par des chaînes de caractères et sont répertoriés dans un dictionnaire.

La fonction possède une arité fixe ou variable ainsi qu'une syntaxe qui décrit ses formes d'appel, et qui participe à la définition du langage en cours. Le langage possède donc un dictionnaire mémorisant les noms des variables et fonctions, et possède une syntaxe décrivant les formes d'appel des fonctions.

Mais, on souhaite pouvoir écrire sans déclaration préalable directement de nouvelles variables et de nouvelles fonctions avec de nouvelles formes d'appel, celles-ci n'étant alors pas présente dans le dictionnaire ni dans la grammaire. c'est donc une règle du dictionnaire et de la grammaire qui devra déterminer si ces nouveaux mots sont des variables ou des fontions ainsi que leur forme d'appel. Et, pour des raisons d'efficience, ces règles devront pouvoir s'appliquer au cours d'une seule lecture de la chaine de caractères. Ces règles constitue la méta-syntaxe et imposent une contrainte sur le dictionnaire et la grammaire.

Par exemple, considérons l'expression suivante :

`x=”"toto"”`

Cette expression possède un sens précis, la fonction `=` s'applique à un couple d'objets comprenant la variable `x` et l'expression `”"toto"”` qui s'évalue en la chaîne `"toto"`. Et on verra qu'après l'exécution de cette instruction, la variable `x` qui initialement n'existait pas, se retrouve avoir le type `"String"` et comme contenu `"toto"`, suivi du caractère nul de fin de chaîne qui occupe deux octets, ce qui occupe en tout exactement `6` octets.

Notez que l'objet constitué juste des 4 caractères `"toto"` est une chaîne-fixe de caractères. Sa taille est fixé par son type ou par son conteneur. Tandis qu'une chaine-fin de caractères possède un caractère de fin qui est le caractère nul. Conventionellement, les objets de type `"String"` sont des chaine-fin de caractères.

Si on souhaite définir une chaine-fixe de caractères, il nous faut trouver une autre notation, un autre symbole, ce sera une simple quote :

`x='"toto"'`

La variable `x` devient de type Modon.

3.2) Les types énumératifs

Le type énumératif énumère ses éléments. Chaque élément résulte d'une évaluation, on remplace le nom des variables par leur valeur brute, on évalue les termes.... Le type énumératif se déclare par une énumération finie de termes entourées d'accolades et séparées par des virgules `{...}`. Il a comme objets les résultats de l'évaluation des termes apparaissant dans l'énumération au moment où la déclaration du type est exécutée.

Et il y a trois sortes de type énumératifs :

Les type de modon on une taille prés-établie. Les types de varon, fixe la taille de leurs objets en consultant leurs premiers bits. Par contre, les types dictionnaires ne permettent pas de définir la taille de leurs éléments simplement en les lisant.

Par exemple si le terme `u` représente la suite de bit `1010`, et si le terme `v` représente la suite de bits `001`, le type `{u,v}` possède deux éléments de tailles différentes que sont la suite de bits `1010` et la suite de bits `001`.

Et si on a besoin d'un type énumératif sans évaluation, on utilise les guillemets ou des quotes pour entourer les termes de l'énumération tel que par exemple le type `{“u“,“v“}`

Lorsque se pose la question de savoir si une donnée brute de taille fixée `X` appartient à un type `T`, on transmet la donnée et sa taille qui est précisée par son conteneur, à un opérateur, `X in T`, qui retourne le bits `1` si c'est vrai et retourne le bits `0` si c'est faux. Cela constitue un teste d'intégrité de `X` en tant qu'objet de type `T`. La même opération se prolonge si `X` possède un type plus précis que Element. On teste alors en plus si le type de `X` peut bien être considéré comme une spécialisation du type `T`.

 

Les types dictionnaires sont utilisés pour traiter des chaînes d'éléments du type en question. Mais à ce niveau intemédiaire de langage, on ne veut pas perdre d'efficacité et l'interprétation d'une telle suites d'éléments doit se faire en une seule lecture. Et cela est possible si on s'en tient à choisire systématiquement les mots les plus grands du dictionnaire. Par exemple considérons le type `{“abc“,“a“,“bcd“,“d“,“"_"“}`, alors la séquence `"abcd"` correspondra à la séquence de mots `"abc", "d"` et non à la séquence de mots `"a", "bcd"`. Et pour désigner la deuxième interprétation, il nous faut recourir à un mot pouvant jouer le rôle de séparateur tel que `"a_bcd"`. Ainsi, il est fait un choix dans l'interprétation des suites de mot d'un même dictionnaire, sans que cela ne réduise la capacité d'expression du langage.

3.3) Le type booléen, `{0,1}`

Le type booléen s'inscrit dans un schéma de construction de type plus général que sont les types énumératifs.

Par convention, le mot `0` désignera un bit contenant `0`, et le mot `1` désignera un bit contenant `1`.

En procédant ainsi on construit petit-à-petit un langage de fond. Ainsi, l'instruction `x=0` sans autre précision et où `x` n'a pas de type défini, va alouer un bit pour la variable `x`, lui attribuer la valeur `0`, et lui attribuer le type booléen.

Le type booléen se déclare comme le type énumératif, `{0,1}`. Les méthodes associées à ce type comprennent naturellement les opérateurs booléens.

3.4) Le type baton

Une chaine-bit sans objet représente une suite de bits à `1` suivi d'un bit à `0`. C'est le type baton. L'inverse qui est une suite de bits à `1` suivi d'un bit à `0` est le type ¬baton.

3.4) Le type des entiers naturels

Puisque le mot `0` désigne un bit contenant `0`, et le mot `1` désigne un bit contenant `1`, qu'est-ce que pourrait désigner le mot `2` ? Il désigne deux bits contenant `10` l'expression binaire de `2`. Et il en est de même pour tous les entiers naturels. Ainsi nous complétons le langage de fond, en introduisant les séquences de chiffres ne commençant pas par zéro, qui sont traduites en leur expression binaire, des données brutes qui sont des séquences de bits ne commençant pas par zéro.

Un mot constitué d'une succession de chiffres s'appelle une suite de chiffres, et si elle ne commence pas par zéro, elle s'évalue en un entier naturel qui se mémorise en une suite de bits ne commençant pas par zéro.

Le type des entiers naturels est un type dont la taille des objets est inconnue.

3.5) Le type Elément

Le type des suites de bits est le type le plus général qui soit, parmi les objets occupant des blocs d'un seul tenant, c'est pourquoi il s'appelle le type Elément, un type dont la taille des objets est inconnue.

On codifie comment écrire une suite de bits, en utilisant l'opérateur `%` de syntaxe collé droite. Ainsi le terme `"%"010010` qui constitue une table binaire dans le langage de fond, s'évalue en la succession de bits `010010`..

En utilisant l'opérateur ":" vu plus loin, de concaténation de suite de bits, l'expression `0:1:0:0` est identique à `"%"0100` et s'évalue en la succession de bits `0100`.

3.6) Le type des Eléments de taille `n` bits

Le type des tables d'exactement `n` bits représente le type des Elément de taille `n` bits. Ce type s'inscrit dans un schéma de construction plus général que sont les types produits, et correspond au type `{0,1}^n`

Le type `{0,1}^n` représente le type racine de tous les éléments de taille de `n` bits, c'est à dire, représente le type des Elément de taille `n` bits.

On ajoute à ce type un interface, c'est à dire des méthodes supplémentaires telles que celles traduisant le code binaire en code décimal, pour produire le type des entiers naturels sur `n` bits. Et on le note en utilisant un opérateur `".."` qui désigne une séquence d'entiers successifs, par l'expression `{0 ".." 2^n"-"1}`

Ainsi l'expression `{a ".." b}``a` et `b` sont des entiers naturels désigne les entiers naturels sur `m` bits entre `a` et `b` compris, où `m` est le nombre de bits nécessaire pour mémoriser en binaire le plus grand des entiers évoqués.

La déclaration d'un entier naturel de taille `n` bits se fait à l'aide d'un constructeur ayant comme premier argument la taille mémoire, `"uint"(n)`. Ainsi, l'instruction `x = "uint"(4,14)` va alouer `4` bits pour la variable `x`, et y mettre l'entier `14` en binaire. Et elle peut s'écrire aussi comme ceci, `x = "uint"(4)(14)`

En s'inspirant du langage fonctionnel Haskell, la fonction `"uint"` appliqué à `4` retourne le constructeur de type des entiers naturels sur `4` bits, puis appliqué à `14` retourne un élément de `4` bits contenant `14` en binaire. L'instruction peut s'écrire aussi à l'aide du séparateur blanc : `x = "uint" 4 14 `

3.7) Les types singletons

Un type singleton ne contient qu'un élément. Et donc ses éléments n'occupent pas de mémoire. Une variable de type singleton ne contient pas de contenue. Parcontre elle possède un type qui est un singleton.

3.8) Le type somme

Étant donné deux types `A,B`, le type somme `A"+"B` représente l'union disjointe des types, c'est à dire le type des éléments pouvant être un élément de `A` ou bien un élément de `B` et en les distiguants selon le chemin emprunté pour les désigner.

`|A"+"B| = |A|"+"|B|`

La somme de deux types énumératifs est un type énumératif couvrant les mêmes objets mais préfixé par une position. Par exemple considérons le type `A = {3,5,7}` et le type `B={2,3,4}`. Le type `A"+"B` est égal à `{0":"3, 0":"5, 0":"7, 1":"2, 1":"3, 1":"4}`. Le `0":"` et le `1":"` indique la position dans l'union disjointe et donc le chemin emprunté pour accéder à l'élément. Et le type sait qu'à la position `0` se trouve un élément de type `A`, et qu'à la position `1` se trouve un élément de type `B`. L'élément `3` est ainsi dédoublé, perçu comme un élément de type `A` une première fois, et perçu comme un élément de type `B` une seconde fois, et ils constituent deux éléments distincts dans le type `A"+"B`.

On remarquera qu'un type énumératif peut être une somme de types singleton. Et on remarquera qu'une somme de deux types d'objets totalement denses constitue un type d'objets totalement denses.

On peut sommer le même type plusieur fois. Considérons par exemple le type `A` des entiers de `0` à`32` :

`A={0 ".." 32}`

C'est un type totalement dense de modon de taille `5` bits. Puis considérons le type `A+A`. Celui-ci admet des objet de `6` bits, le premier bit déterminant s'il sagit d'un élément du premier `A` ou un élément du second `A`. Maintenant faisons une troisième sommation `(A+A)+A`. Ce type admet des objets de `6` ou `7` bits, c'est un type de varon où le premier bit détermine sa taille.

On défini le type produit par un entier strictement positif. Le type `nA` correspond à la somme de `A` avec lui-même `n` fois, mais sous la forme d'un modon de taille minimale. L'objet comprend `k` premiers bits formant un sous-objet de type `{0 ".." n"-"1}` suivi d'un objet de type `A`. Autrement dit :

`nA = {0 ".." n"-"1}"×"A`

Et donc le modon de type `nA` est totalement dense lorsque `n` est une puissance de `2` et que le type `A` est totalement dense.

3.9) Le type produit

Étant donné deux types `A,B`, le type produit `A"×"B` représente le type des couples composé d'un premier élément de type `A` et d'un second élément de type `B`.

Cette définition est ambigüe lorsque `A` est un dictionnaire et que `B` n'est pas un modon. C'est pourquoi on s'interdit d'opérer le produit entre un type dictionnaire et un type qui n'est pas un type de modon.

3.10) Le type exposant

Étant donné deux types `A,B`, le type exposant `B^A` représente le type des applications de `A` vers `B` définies par leur graphes. Il est un sous-type du type des applications `A"→"B`. Un objet de ce type contient une liste d'objet appartenant à `A"×"B`

Cette définition est ambigüe lorsque `A` ou`B` sont de type dictionnaire. C'est pourquoi on s'interdit d'opérer des puissances entre types si l'un des type est un type dictionnaire.

4) Les opérations fondamentales

à partir d'un modon de type `A`, il existe une opération fondamentale appelée adressage indexé qui correspond à une application de `A` vers un type de modon `B`, et qui occupe `2^N_A N_B` bits. Toutes les application de A vers B sont définissables ainsi.

à partir d'un type `A`, il existe une opération fondamentale appelée hachage qui correspond à une application `varphi` spécifique de `A` vers `{0 ".." 2^n-1}`. Selon le nombre d'éléments de `A` noté `|A|` et le nombre `n`, la probabilité qu'une image `varphi(a)` soit égale à une autre image `varphi(b)` avec `a`=/=`b` peut être réduite.

---- 19 avril 2022 ----

 

4) Les conversions fondamentales

Un type est totalement dense si toutes les combinaisons de bits correspondent à des éléments distincts. Le choix d'un élément de ce type, contient une quantité d'information égale à son nombre de bits. Une liste de tels objects est donc incompressible.

Un type est dense si le choix d'un élément de ce type contient une quantité d'information strictement comprise entre son nombre de bit et son nombre de bit moins un. Un tel élément isolé est incompressible.

On mesure la dispertion d'un type de modon en prenant le rapport du nombre de bits des objets par le nombre de bits nécessaires pour compter tous les éléments du type c'est à dire par le logarithme en base `2` du nombre de ses éléments. Ainsi, par exemple, les listes de `3` chiffres décimaux forment un type d'objet de `3` octets qui possède `1000` éléments. La dispertion de ce type est donc égale à `24"/"log_2(1000)` c'est-à-dire à peu près à `2.9` et cela signifie que l'objet est compressable en divisant par `2.9` sa taile en nombre de bits. Les types totalement dense ont une dispersion de `1`.

Un type énumératif peut être converti en un autre type énumératif, et cela correspond à une bijection. Il existe deux procédés de calcul applicatif particulièrement efficace que sont l'adressage indexé et le hachage.

L'application d'un modon de type A sur un modon de type B se définit en déployant une suite de `2^N` d'objets de type B où N est la taille des objets de type A (en nombre de bits).

L'application d'un modon de type A sur un varon de type B se fait en déployant la suite des éléments de type B ainsi qu'une suite de `2^N` d'objets de type pointeur d'objet de type B, où N est la taille des objets de type A (en nombre de bits).

L'application d'un objet de type A sur un modon de type B se fait en déployant une suite de `N` d'objets de type B où N est la taille de la table de hachage objets de type A (en nombre de bits). se fait en hachant l'objet de type Adéployant la suite des éléments de type B ainsi qu'une suite de `2^N` d'objets de type pointeur d'objet de type B, où N est la taille des objets de type A (en nombre de bits).

 

---- 18 avril 2022 ----

 

 

 

Le type dictionnaire est converti en un type chaine (chaine-fixe, chaine-param, chaine-fin ou chaine-bit).

 

 

pour chaque valeur appartenant à `A`, une valeur appartenant à `B`.

Il existe 2 représentations possibles d'un graphe `B^A`. Soit comme liste de couple de A"×"B, ou soit comme une liste d'éléments de B

L'effficience nous oblige à certaines contraintes ou compléments programmatifs concernant `A` et `B`. Si `A` est un type modon dense, et que `B` est un type modon, la construction du type `B^A` ne pose pas de problème. Un objet de ce type se compose de `2^n` blocs où `n` est la taille des objects de type `A` et où chaque bloc contient un ojet de type `B`. Mais il se peut que l'on souhaite réduire la taille de ces objets. Il y a deux façons cumulables de réduire la taille de ces objets, On remplace le modon de type `A` par sa version dense, et on remplace le modon de type `B` par sa version dense. Et dans le cas ou `B` n'est pas un modon, On extrait juste l'image dont on fait un type et on en prend la version dense.

 

La bijection se traduit par deux procédure de calcul, l'une dans un sens de la conbersion, l'autre dans le sens inverse de la conversion.

 

On concoit une première conversion, transformant un type en un type dense, et qui consiste à numéroter les éléments du type.

 

 

L'effficience nous oblige à certaines contraintes ou compléments programmatifs concernant `A` et `B`. Si `A` est un type modon dense, et que `B` est un type modon, la construction du type `B^A` ne pose pas de problème. Un objet de ce type se compose de `2^n` blocs où `n` est la taille des objects de type `A` et où chaque bloc contient un ojet de type `B`. Mais il se peut que l'on souhaite réduire la taille de ces objets. Il y a deux façons cumulables de réduire la taille de ces objets, On remplace le modon de type `A` par sa version dense, et on remplace le modon de type `B` par sa version dense. Et dans le cas ou `B` n'est pas un modon, On extrait juste l'image dont on fait un type et on en prend la version dense.

 

3.8) Les types énumératifs denses

Les types énumératif peuvent être augmenté par une numérotation continue de leur objet.

 

une numérotation sans trou de leur objects. On numérote chaque objet de `0` à `N-1` où `N` est le nombre d'objets.

e type énumératif dense est la forme compressée du type énumératif. Ses objets sont numérotés et ces leur numéros (indexes) qui sont mémorisés. Il se déclare par une énumération finie d'éléments entourée de crochet et séparés par des virgules `[...]`. Un objet de ce type `T` est un index de type `{0 ".." |T|"-"1}` référençant l'élément correspondant dans l'énumération.

Le type possède un référenceur transformant l'indexe en l'expression de l' élément correspondant, et un codeur transformant l'expression de l' élément en son indexe mais qui n'est pas très efficient.

Ce type est dense, c'est à dire que les objets de ce type sont denses. Pris individuellement ils ne peuvent être compressé davantage. Et si  `|T|` est une puissance de `2` alors le type est totalement dense, c'est à dire que ses objects sont totalement denses. Chaque combinaisons distincte de `|T|` bits correspond à un objet distinct de type `T` et réciproquement.

3.9) Les types énumératifs hachés

Le type énumératif haché est une autre forme compressée du type énumératif, mais compressé partiellement à l'aide d'une table de hachage de `2^n` cases. La donnée est transformée en un code de hachage singularisé à l'initalisation du type. Ce type possède des éléments tous de même tailles `n` bits.

Le type énumératif haché ce déclare par une énumération finie d'éléments entourée d'accolades fantaisie et séparés par des virgules `❴...❵`. Un objet de ce type `T` contient un code de hachage sur `n` bits, où `2^n` désigne le nombre de cases de la table de hachage de `T`.

Le type possède un référenceur transformant le code de hachage en l'élément correspondant.

Le type possède un référenceur transformant le code de hachage en l'expression de l'élément correspondant, et un codeur efficace transformant l'expression de l'élément en son code de hachage.

3.10) Le type somme

Étant donné deux types `A,B`, le type somme `A"+"B` représente l'union disjointe des types, c'est à dire le type des éléments pouvant être un élément de `A` ou bien un élément de `B` et en les distiguants selon le chemin emprunté pour les désigner.

`|A"+"B| = |A|"+"|B|`

La somme de deux types énumératifs est un type énumératif couvrant les mêmes objets mais préfixé par une position. Par exemple considérons le type `A = {3,5,7}` et le type `B={2,3,4}`. Le type `A"+"B` est égal à `{0":"3, 0":"5, 0":"7, 1":"2, 1":"3, 1":"4}`. Le `0":"` et le `1":"` indique la position dans l'union disjointe et donc le chemin emprunté pour accéder à l'élément. Et le type sait qu'à la position `0` se trouve un élément de type `A`, et qu'à la position `1` se trouve un élément de type `B`. L'élément `3` est ainsi dédoublé, perçu comme un élément de type `A` une première fois, et perçu comme un élément de type `B` une seconde fois, et ils constituent deux éléments distincts dans le type `A"+"B`.

On remarquera qu'un type énumératif peut être une somme de types singleton. Et on remarquera qu'une somme de deux types d'objets totalement denses constitue un type d'objets totalement denses.

On peut sommer le même type plusieur fois. Considérons par exemple le type `A` des entiers de `0` à`32` :

`A={0 ".." 32}`

C'est un type totalement dense de modon de taille `5` bits. Puis considérons le type `A+A`. Celui-ci admet des objet de `6` bits, le premier bit déterminant s'il sagit d'un élément du premier `A` ou un élément du second `A`. Maintenant faisons une troisième sommation `(A+A)+A`. Ce type admet des objets de `6` ou `7` bits, c'est un type de varon où le premier bit détermine sa taille.

On défini le type produit par un entier strictement positif. Le type `nA` correspond à la somme de `A` avec lui-même `n` fois, mais sous la forme d'un modon de taille minimale. L'objet comprend `k` premiers bits formant un sous-objet de type `{0 ".." n"-"1}` suivi d'un objet de type `A`. Autrement dit :

`nA = {0 ".." n"-"1}"×"A`

Et donc le modon de type `nA` est totalement dense lorsque `n` est une puissance de `2`.

3.11) Le type produit

Étant donné deux types `A,B`, le type produit `A"×"B` représente le type des couples composé d'un premier élément de type `A` et d'un second élément de type `B`.

Cette définition est sans ambiguité lorsque `A` n'est pas un dictionnaire ou lorsque `B` est un type de modon. C'est pourquoi on s'interdit d'opérer des produits dont le premier type est un type dictionnaire si le second type n'est pas un type de modon.

3.12) Le type exposant

Étant donné deux types `A,B`, le type exposant `B^A` représente le type des applications de `A` vers `B` définies par leur graphes. Il est un sous-type du type des applications `A"→"B`. Un objet de ce type contient pour chaque valeur appartenant à `A`, une valeur appartenant à `B`.

L'effficience nous oblige à certaines contraintes ou compléments programmatifs concernant `A` et `B`. Si `A` est un type modon dense, et que `B` est un type modon, la construction du type `B^A` ne pose pas de problème. Un objet de ce type se compose de `2^n` blocs où `n` est la taille des objects de type `A` et où chaque bloc contient un ojet de type `B`. Mais il se peut que l'on souhaite réduire la taille de ces objets. Il y a deux façons cumulables de réduire la taille de ces objets, On remplace le modon de type `A` par sa version dense, et on remplace le modon de type `B` par sa version dense. Et dans le cas ou `B` n'est pas un modon, On extrait juste l'image dont on fait un type et on en prend la version dense.

4) Langage d'opérateurs

Les types précédents concernent des donnée brutes souvent denses, voir totalement denses. Par contre il n'en est pas de même pour les formules d'un langage, à cause d'une redondance quasi-ontologique propre aux langages. C'est pourquoi apparaît un autre genre de type qui les consacre.

4.1) Le type des `A`-phrases

Étant donné un type `A` de genre dictionnaire. C'est à dire qu'un objet de type `A` est une suite de blocs de même tailles, dont une copie existe dans le dictionnaire `A`. Les `A`-phrases doivent satisfaire une règle d'intégrité supplémentaire pour des raisons d'efficience. C'est ce qui les différencie des suites d'objets collés de type `A` : Chaque objet de type `A` se trouvant dans une `A`-phrase ne doit pas pouvoir être complété par des blocs suivants concomitant pour former un objet plus grand de type `A`. Cette condition d'intégrité assure que la succession des blocs peut être lue en une seule fois en choissant toujours les mots les plus long possible du dictionnaire.

4.1) Le type des `A`-phrases

Étant donné un type `A` de genre dictionnaire. C'est à dire qu'un objet de type `A` est une suite de blocs de même tailles, dont une copie existe dans le dictionnaire `A`. Les `A`-phrases doivent satisfaire une règle d'intégrité supplémentaire pour des raisons d'efficience. C'est ce qui les différencie des suites d'objets collés de type `A` : Chaque objet de type `A` se trouvant dans une `A`-phrase ne doit pas pouvoir être complété par des blocs suivants concomitant pour former un objet plus grand de type `A`. Cette condition d'intégrité assure que la succession des blocs peut être lue en une seule fois en choissant toujours les mots les plus long possible du dictionnaire.

4.2) Le type des `A`-termes

Étant donné un type `A` de genre dictionnaire, que l'on complète par une grammaire qui définit une syntaxe. Les `A`-termes sont des `A`-phrases respectant cette syntaxe.

Le `A`-terme possède une seconde représentation dite compilée sous forme d'arbre.

À quoi ressemble la grammaire que nous évoquons ici et qui définit la syntaxe ?

Le langage doit être le plus proche possible de celui utilisé par l'utilisateur, le plus proche possible de la données, afin qu'une simple recopie permette d'en assurer une transcription exacte, et finalement que l'évolution du programme soit parallèle à l'évolution de sa conception. On résume cette propension en la qualité de choisir le langage le plus adapté au problème, résolvant de faite la moitier du problème.

Puisque nous créons un langage adapté sur mesure pour chaque problème, il n'est plus à craindre de s'égarer dans l'élaboration d'un langage de fond spécifique épousant le hardware.

5) Syntaxe

Les grammaires que nous allons utilisées sont plus simples que celles classiques appelées grammaires de caractères opérant par substitution de séquence de caractères et de symboles non-terminaux. À leur place, nous utiliserons des grammaires d'opérateurs, qui comme leur nom l'indique, précise la syntaxe des opérateurs.

La syntaxe est liés à l'arité des opérateurs. Etant donné un ensemble d'éléments `E`, L'opérateur est par définition une application de `E^n"→"E^m` c'est à dire défini partout dans `E^n` et produisant un élément de `E^m`. Cela permet de définir formellement pour chaque opérateur une notion d'arité d'entré et d'arité de sortie.

Des opérateurs plus généraux peuvent être définis comme des applications de `E"*""→"E"*"` possèdant de faite toutes les arités d'entrées possibles et une arité de sortie variable.

Ces conceptions s'inscrivent dans un problème mathématique plus vaste généralisant la notion d'opérateur, connu sous le nom de " Langage alpha "

6) Langage alpha

Considérons un ensemble d'éléments `E`.

Un opérateur dans `E` est une application de `E^n"→"E^m`. L'opérateur prend `n` arguments pour produire `m` résultats.

L'ensemble des opérateurs d'arité d'entrée `n` et d'arité de sortie `m` se note `E^n"→"E^m`.

Un opérateur `s` se note sous la forme d'un graphe `{AAx, x"↦"s(x)}` où la formule universelle entre crochet est développée en un ensemble d'arcs. L'opérateur `s` se note d'une seconde façon plus simplifiée par `(x"↦"s(x))` où les parenthèses dénote l'ouverture d'un bloc, et où l'expression `x"↦"` déclare une variable universelle `x`.

L'intéropérabilité devant être optimale, et la notion d'élément mathématique devant être la plus générale possible, tout élément ou opérateur d'arité quelconque doit pouvoir être unifiable à tout élément et opérateur d'arité quelconque. L'élément est donc vu soit comme passif (élément) ou comme actif (opérateur). Le langage alpha rend possible tout cela en simplifiant considérablement les choses car il n'utilise que des opérateurs unaires.

Une loi de composition est équivalente à un rôle d'opérateur unaire pour tout les éléments.

Un opérateur binaire interne c'est à dire de `E^2"→"E` s'appelle une loi de composition interne dans `E`. On ne traite que d'opérateur interne dans `E`, c'est à dire également dans `E^2`, `E^3`, ... , `E^n` ou `E"*"`.

Chaque loi de composition peut être remplacée par un rôle d'opérateur unaire accordé à tous les éléments. Par exemple étant donné la loi `"∗"` de `E"×"E"→"E`, on définie un rôle d'application unaire pour chaque élément de `E` par la formule suivante :

`AAxAAy, x(y) = x"∗"y`

L'écriture verbeuse mentionne explicitement l'application `varphi` qui transforme l'élément en son rôle d'opérateur unaire.

`varphi = (x"↦"( y"↦"x"∗"y))`

`AAxAAy, varphi(x)(y) = x"∗"y`

Le contexte ajoute aux éléments de `E` leur unique rôle d'application, de telle sorte qu'il n'est pas nécessaire de mentionner `varphi`, et que l'appel `x(y)` signifie directement et sans ambiguité `varphi(x)(y)`.

Mais s'il existe une seconde loi de composition notée par exemple `"⋅"`, donnant un second rôle d'opérateur unaire à tous les éléments. Pour le différentier du premier rôle, on le note à l'aide de parenthèses d'appel différentes :

`AAxAAy, x[y] = x"⋅"y`

Une loi de composition vierge.

Il est possible d'ajouter un opérateur binaire vierge, qui s'effectue sans perte d'information, autrement dit, qui crée une forme de couple d'éléments. On étend l'ensemble des éléments `E` en y ajoutant ces couples d'éléments et donc aussi ces couples d'éléments qui peuvent être à leur tour des couples d'éléments et ainsi de suite, autrement dit, en y ajoutant une forme d'arbres binaires dont les feuilles appartiennent à `E`. L'ensemble résultant `A` s'appelle l'extension élémentaire libre par l'ajout d'un opérateur binaire, par exemple de nom `"∗"` :

`A = E["∗"(".,.")]`

Cette extension s'opère sans qu'il y ait le moindre arbitraire. Quelque soit `x` et `y` appartenant à `A`, nous avons bien `x"∗"y` appartenant à `A`. Puis comme précédement, chaque élément de `A` possède donc un second rôle d'opérateur unaire dans `A`.

Tous les éléments de `A` sont des opérateurs de `A"→"A`

L'intéropérabilité devant être optimale, et la notion d'élément mathématique devant être la plus générale possible, tout élément doit pouvoir être unifiable à un opérateur unaire. L'élément est donc vu soit comme passif (élément) ou comme actif (opérateur).

Et on peut définir un rôle d'opérateur `n`-aire pour tous les éléments, de la même façon par extension élémentaire libre par l'ajout d'un opérateur `(n"+"1)`-aire vierge. Ainsi l'élément peut posséder plusieurs rôles d'opérateurs. Et si chacun d'eux à une arité d'entrée distincte, l'appel d'un opérateur spécifiant son nombre d'argument, il n'est pas nécessaire de préciser quelle rôle d'opérateur est utilisé. Il n'y a pas d'ambiguité.

Les couples d'éléments

On veut définir ce qu'est un couple d'éléments et en faire un élément. Pour cela, on définit une loi de composition vierge, autrement dit, qui crée une seconde forme de couples d'éléments. On étend l'ensemble des éléments `A` en y ajoutant ces couples d'éléments et donc aussi les couples d'éléments qui peuvent être à leur tour des couples d'éléments et ainsi de suite, autrement dit, en y ajoutant une seconde forme d'arbres binaires dont les feuilles appartiennent à `A`. L'ensemble résultant `C` s'appelle l'extension élémentaire libre par l'ajout d'un opérateur binaire de nom explicite `sf"virgule"` et de symbole "," :

`C = A[sf"virgule"(".,.")]`

Ainsi, les couples d'éléments de `C` constituent bien des éléments de `C`.

Les séquence d'éléments.

Pour cela on quotiente la structure par la relation d'associativité

`D = (A[sf"virgule"(".,.")])/{AAxAAyAAz,((x,y),z) = (x,(y,z))}`

Ainsi, les séquences d'éléments de `D` constituent bien des éléments de `D`. En procédant ainsi, on applatit chaque arbre en une séquence d'un seul niveau. Si la constrution de séquence d'élément et la même que celle utilisé par l'opérateur de Kleene D"*", alors on en conclue que :

`D"*" = D`

Chaque élément de `D` possède un rôle d'opérateur de `D"→"D`, et donc aussi de `D"*""→"D"*"`. Le langage n'utilise que des opérateurs unaires qui peuvent être interprétés comme des opérateurs possédant toutes les arités d'entré et une arité de sortie variables.

 

------- 6 avril 2022 -------

 

 

 

 

 

 

 

Le langage alpha rend possible tout cela en simplifiant considérablement les choses car il n'utilise que des opérateurs unaires.

 

Cette seconde loi peut également être remplacée par un rôle d'opérateur unaire accordé à tous les éléments, et que l'on note par une seconde forme d'appel `["."]`. La loi "virgule" est une application de `A"×"A->A``A` est l'extension libre de `E` par l'ajout de l'opérateur binaire "virgule". On définie un second rôle d'application unaire pour chaque élément de `A` par la formule suivante :

`AA(x,y)"∈"A^2, x[y] = (x,y)`

Puis on peut poser une syntaxe allégeant l'écriture faisant que `(a,(b,(c,d)))` se note `(a,b,c,d)`. Chaque élément `x` possède deux rôles, il est un opérateur unaire de `A"→"A` noté avec la forme d'appel `x(".")`, et il est un opérateur unaire de `A "→" A` noté avec la forme d'appel `x["."]`. Ce sont bien des applications et non de simples fonctions au domaine de définition lâche. Et dans ce cadre plus large, il est possible d'unifier des éléments d'arités distinctes. La lâcheté est reportée dans l'étendue de `A`.

Tout opérateur doit être unifiable à tout autre opérateur même s'il ne possède pas la même arité d'entrée. Ainsi il doit être possible d'unifier un opérateur binaire et un opérateur ternaire, formant un opérateur d'arité d'entrée à la fois 2 et 3. L'arité d'entrée devient un sous-ensemble d'entiers naturels, contenant déjà 0 car tout opérateur est aussi un élément lorsqu'il est vu globalement comme un élément. L'opérateur est alors par définition une application de :

`E uu E^(n_1)uu E^(n_2)uu E^(n_3)uu...)-> E^m`

La généralisation opérée par le langage alpha va simplifier considérablement les choses car elle n'utilise que des opérateurs unaires.

Un opérateur binaire s'appelle une loi de composition, et chaque loi de composition peut être remplacée par un rôle d'opérateur unaire accordé à tous les éléments. Par exemple étant donné la loi `"∗"` de `E"×"E->E`, on définie un rôle d'application unaire pour chaque élément de `E` par la formule suivante :

`AA(x,y) "∈" E^2, x(y) = x"∗"y`

Puis on définit une seconde loi de composition qu'est la virgule et qui permet de créer les couples d'éléments. Cette seconde loi peut également être remplacée par un rôle d'opérateur unaire accordé à tous les éléments, et que l'on note par une seconde forme d'appel `["."]`. La loi "virgule" est une application de `A"×"A->A``A` est l'extension libre de `E` par l'ajout de l'opérateur binaire "virgule". On définie un second rôle d'application unaire pour chaque élément de `A` par la formule suivante :

`AA(x,y)"∈"A^2, x[y] = (x,y)`

Puis on peut poser une syntaxe allégeant l'écriture faisant que `(a,(b,(c,d)))` se note `(a,b,c,d)`. Chaque élément `x` possède deux rôles, il est un opérateur unaire de `A"→"A` noté avec la forme d'appel `x(".")`, et il est un opérateur unaire de `A "→" A` noté avec la forme d'appel `x["."]`. Ce sont bien des applications et non de simples fonctions au domaine de définition lâche. Et dans ce cadre plus large, il est possible d'unifier des éléments d'arités distinctes. La lâcheté est reportée dans l'étendue de `A`.

 

L'ensemble des opérateurs nullaires dans `E` se note `"→"E`. L'opérateur nullaire produisant `e` se note `{"↦"e}` ou `("↦"e)`. L'opérateur identité dans `E` se note `{AAx, x"↦"x}` ou de façon simplifiée `(x"↦"x)`.

 

Un élément de `E` peut être considéré comme un opérateur d'arité d'entrée nulle et d'arité de sortie 1. Mais il s'agit là d'un choix unificateur de notre part, d'une unification, qui se note par l'axiome suivant :

`AAx, ("↦"x) = x`

Sans cet axiome, il existe une distinction entre l'opérateur nullaire produisant l'élément, et l'élément en question.

Un couple d'éléments de `E` est un opérateur d'arité d'entré 0 et d'arité de sortie 2. Ce que nous résumons par la formule `"→"(E"×"E)=E×E`. Et l'opérateur virgule qui construit le couple est défini par l'application l'identité de `E"×"E->(E"×"E)`.

 

 

 

------- 1 avril 2022 -------

 

Un couple d'éléments de `E` est un opérateur d'arité d'entré 0 et d'arité de sortie 2. Ce que nous résumons par la formule `"→"(E"×"E)=E×E`. Et l'opérateur virgule qui construit le couple est défini par l'application l'identité de `E"×"E->(E"×"E)`.

Mais il est aussi d'arité de sortie 1 lorsque le couple est perçu globalement comme un élément.

Cette dernière remarque peut signifier deux choses :

Soit on étend l'ensemble des éléments `E` en y ajoutant les couples d'éléments et donc aussi les couples d'éléments qui peuvent être à leur tour des couples d'éléments et ainsi de suite, soit les arbres binaires dont les feuilles appartiennent à `E`. L'ensemble résultant `A` s'appelle l'extension élémentaire libre par l'ajout d'un opérateur binaire (la virgule) :

`A = E[","(".,.")]`

Et chaque opérateur devra opérer dans `A`.

Ou soit on distingue les éléments de `E` et les éléments de `E^2`.

------- 31 mars 2022 -------

 

L'intéropérabilité devant être optimale, et la notion d'élément mathématique devant être la plus générale, tout élément doit pouvoir être unifiable à tout autre élément même s'il ne possède pas la même arité de sortie. Ainsi il doit être possible d'unifier un couple d'éléments avec un éléments, formant un élément d'arité de sortie à la fois 2 et 3. L'arité de sortie devient un sous-ensemble d'entiers naturels, contenant déjà 1 car tout opérateur est aussi un élément lorsqu'il est vu globalement comme un élément.

Tout opérateur doit être unifiable à tout autre opérateur même s'il ne possède pas la même arité d'entrée. Ainsi il doit être possible d'unifier un opérateur binaire et un opérateur ternaire, formant un opérateur d'arité d'entrée à la fois 2 et 3. L'arité d'entrée devient un sous-ensemble d'entiers naturels, contenant déjà 0 car tout opérateur est aussi un élément lorsqu'il est vu globalement comme un élément. L'opérateur est alors par définition une application de :

`E uu E^(n_1)uu E^(n_2)uu E^(n_3)uu...)-> E^m`

La généralisation opérée par le langage alpha va simplifier considérablement les choses car elle n'utilise que des opérateurs unaires. Un opérateur binaire s'appelle une loi de composition, et chaque loi de composition peut être remplacée par un rôle d'opérateur unaire accordé à tous les éléments. Par exemple étant donné la loi `"∗"` de `E"×"E->E`, on définie un rôle d'application unaire pour chaque élément de `E` par la formule suivante :

`AA(x,y) "∈" E^2, x(y) = x"∗"y`

Puis on définit une seconde loi de composition qu'est la virgule et qui permet de créer les couples d'éléments. Cette seconde loi peut également être remplacée par un rôle d'opérateur unaire accordé à tous les éléments, et que l'on note par une seconde forme d'appel `["."]`. La loi "virgule" est une application de `A"×"A->A``A` est l'extension libre de `E` par l'ajout de l'opérateur binaire "virgule". On définie un second rôle d'application unaire pour chaque élément de `A` par la formule suivante :

`AA(x,y)"∈"A^2, x[y] = (x,y)`

Puis on peut poser une syntaxe allégeant l'écriture faisant que `(a,(b,(c,d)))` se note `(a,b,c,d)`. Chaque élément `x` possède deux rôles, il est un opérateur unaire de `A"→"A` noté avec la forme d'appel `x(".")`, et il est un opérateur unaire de `A "→" A` noté avec la forme d'appel `x["."]`. Ce sont bien des applications et non de simples fonctions au domaine de définition lâche. Et dans ce cadre plus large, il est possible d'unifier des éléments d'arités distinctes. La lâcheté est reportée dans l'étendue de `A`.

 

--- 31 mars 2022 ----

 

 

 

Il existe un

et elle correspond au type `B^|A|` munie d'une méthode de traduction entre `{0 ".." |A|}` et `A`. Puis au cas où `B` est un type dictionnaire, on le tranforme implicitement en type chaines.

C'est pourquoi le type `B^A` est interprété différamment selon les cas : Lorsque `A` n'est pas dense, il est transformé en type dense `[@A]`

, et lorsque B n'est pas un type modon

`B` est un type dictionnaire, on le tranforme implicitement en type chaines. que si `A` est dense,

On remarquera que `B^A` est totalement dense si `A` et `B` sont totalement dense.

--- 23 mars 2022 ----

 

 

 

 

 

 

Dominique Mabboux-Stromberg