Types
Type List
ListImplémentée sous forme de liste simplement chaînée : → 1 liste = 1 élément (Head) + 1 sous-liste (Tail) → Construction nommée Cons et notée ::
Pour éviter récursion infinie, besoin d'un cas de "sortie" : → Liste vide nommée Empty et notée []
👉 Type union générique et récursif :
type List<'T> =
| ( [] )
| ( :: ) of head: 'T * tail: List<'T>Alias de types
Par défaut,
Listfait référence au type (ou au module) F#listest un alias du typeListde F#, utilisé souvent avec la notation OCaml : →let l : string list = ...Si on fait un
open System.Collections.Generic,Listfera référence à la liste mutable C# et masquera le typeListF# mais sera fusionné avec le moduleListF# !Pour éviter cela, on peut utiliser l'alias
ResizeArraypour référencer la liste mutable C# directement, sans devoir faireopen System.Collections.Generic.
Littéraux
0
[]
[]
Empty
1
[1]
1 :: []
Cons (1, Empty)
2
[2; 1]
2 :: 1 :: []
Cons (2, Cons (1, Empty))
3
[3; 2; 1]
3 :: 2 :: 1 :: []
Cons (3, Cons (2, Cons (1, Empty)))
Vérification par décompilation avec SharpLab.io :
Immuable
Il n'est pas possible de modifier une liste existante. → C'est cela qui permet de l'implémenter en liste chaînée.
💡 L'idée est de créer une nouvelle liste pour signifier un changement.
→ Utiliser les opérateurs Cons (::) et Append (@) 📍
Initialisation
Exercices 🕹️
1. Implémenter la fonction rev
revInverse une liste : rev [1; 2; 3] ≡ [3; 2; 1]
2. Implémenter la fonction map
mapTransforme chaque élément : [1; 2; 3] |> map ((+) 1) ≡ [2; 3; 4]
💡 Astuces
→ Pattern matching liste vide [] ou Cons head :: tail
→ Sous-fonction (tail-) recursive
Solution 🎲
💡 Vérification avec sharplab.io de la tail recursion compilée en boucle while
Vérification en console FSI ✅
Type Array
ArrayDifférences /
List: mutable, taille fixe, accès indexé en O(1)Signature générique :
'T array(récemment recommandée) ou'T []Littéral et comprehension : similaires à
List
Accès indexé & mutation
Accès par index : my-array.[my-index]
⚠️ Piège : ne pas oublier le . avant les crochets [] ❗
🎁 F♯ 6.0 supporte sans le . : my-array[my-index]
Slicing
Renvoie un sous-tableau entre les indices start..end optionnels
💡 Marche aussi avec une string : "012345".[1..3] ≡ "123"
Alias ResizeArray
ResizeArray☝️ Ne pas confondre le type List<T> de F♯ avec celui de .NET dans le namespace System.Collections.Generic.
Même si les listes .NET ne sont pas très souvent utilisées en F♯, quand on en a besoin (par exemple en interop), il vaut mieux utiliser l'alias ResizeArray qui permet d'éviter la confusion avec les listes F♯.
☝️ Ne pas confondre l'alias ResizeArray avec le type Array de F♯.
Type Seq
Seqtype Seq<'T> = IEnumerable<'T> → Série d'éléments de même type
Lazy : séquence construite au fur et à mesure lors de son itération ≠ List construite dès la déclaration
→ Peut offrir de meilleures performances qu'un List pour une collection avec beaucoup d'éléments et qu'on ne souhaite pas parcourir entièrement.
Syntaxe
seq { comprehension }
Séquence infinie
Option 1 : appeler la fonction Seq.initInfinite : → Seq.initInfinite : (initializer: (index: int) -> 'T) -> seq<'T> → Paramètre initializer sert à créer l'élément d'index (>= 0) spécifié
Option 2 : écrire une fonction récursive générant la séquence
Type Set
SetCollection auto-ordonnée d'éléments uniques (sans doublon) → Implémentée sous forme d'arbre binaire
Informations
→ count, minElement, maxElement
Opérations
→ Union, Différence, Intersection (idem ensembles en Math)
Union
∪
+
Set.union
Set.unionMany
Différence
⊖
-
Set.difference
Set.differenceMany
Intersection
∩
Set.intersect
Set.intersectMany
Exemples :
A
[ 1 2 3 4 5 ]
[ 1 2 3 4 5 ]
[ 1 2 3 4 5 ]
B
[ 2 4 6 ]
[ 2 4 6 ]
[ 2 4 6 ]
Résultat
A + B
[ 1 2 3 4 5 6 ]
A - B
[ 1 3 5 ]
A ∩ B
[ 2 4 ]
Type Map
MapTableau associatif { Clé → Valeur } ≃ Dictionary immutable en C♯
Accès par clé
Dictionnaires
dict function
dict functionConstruit un IDictionary<'k, 'v> immutable ❕ à partir d'une séquence de pairs clé/valeur
readOnlyDict function
readOnlyDict functionConstruit un IReadOnlyDictionary<'k, 'v> à partir d'une séquence de pairs clé/valeur
👉 Recommendation Préférer
readOnlyDictàdictcar l'interfaceIReadOnlyDictionary<'k, 'v>est + fidèle à l'implémentation sous-jacente. Au contraire,dictne respecte pas le principe de substitution de Liskov !
KeyValue active pattern
KeyValue active patternPermet de déconstruire une entrée
KeyValuePaird'un dictionnaire en passant par un tuple(clé, valeur)Signature:
Performance des lookups (find)
find)🔗 High Performance Collections in F#, Compositional IT, Jan 2021
Map vs Dictionary
Map vs DictionaryFonction readOnlyDict permet de créer rapidement un IReadOnlyDictionary → à partir d'une séquence de tuples key, item → très performant : 10x plus rapide que Map pour le lookup
Dictionary vs Array
Dictionary vs Array→ Array suffit si peu de lookups (< 100) et peu d'éléments (< 100)
→ Dictionary sinon
Set et Map vs IComparable
Set et Map vs IComparableNe marchent que si les éléments (d'un Set) ou les clés (d'une Map) sont comparables !
🎉 Compatibles avec tous les types F♯ (cf. égalité et comparaison structurelles)
⚠️ Pour les classes : implémenter IComparable (mais pas IComparable<'T>)
Last updated
Was this helpful?