You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: fr/lessons/basics/containers.md
+81-1Lines changed: 81 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -513,9 +513,89 @@ Un lecteur averti notera qu'en réalité la _map_ n'est pas mise à jour. Le sec
513
513
514
514
Les _maps_ sont vraiment très adaptées pour persister en mémoire des états qui devront être récupérer à partir d'une clé, d'un type préalablement définit. Ceci est du au bonnes performances de recherche à partir des clés qui caractérisent les _maps_ grâce à la contraite de tri sur leurs clés, on a une complexité asymptotique (`𝛰(log n)`). Un exemple évident est le stockage de session sur un serveur d'une application web. L'état de la session peut être stocké dans une _map_ avec l'id présent dans le _cookie_ de session comme clé. Ainsi, l'état de la session est accessible de manière performante via cette _map_ pour chaque requête. Cette solution ne permet pas non plus de gérer un nombre infini de session mais vous serez étonnés de voir à quelle point elle est efficace, pour répondre simplement aux besoins de la plupart des applications !
515
515
516
-
### Une _Map_ avec des clés sans contraintes de tri : _HashMaps_
516
+
### Une _Map_ avec "des clés sans contraintes de tri" : _HashMaps_
517
517
518
518
Dans certains cas, on veut utiliser comme clé, un type qui ne respecte pas la contrainte de tri. Les _Hashmap_ sont faites pour ça. Une _Hashmap_ va "hacher" la clé (quelque soit le type tant qu'il est _hashable_) pour la rendre "ordonnable" !
519
519
520
520
Le module qui exporte le type `HashMap` et ses fonctions est `Data.HashMap.Strict`, il fait parti du _package_`unordered-containers`. L'_api_ est identique à celle de `Map` excepté que la contrainte sur la clé est `Hashable k` au lieu de `Ord k`.
521
521
522
+
## Vectors
523
+
524
+
Parfois on souhaite avoir une _list_ comme _conatiner_ avec de bonnes performances d'accès aux données. Dans la plupart des langages, les _arrays_ sont la structure de données de base pour gérer des séquences de données. Haskell possède également ce type de structure de données et l'implémentation la plus populaire est le type `Vector` de la bibliothèque `vector`.
525
+
526
+
Un des aspects les plus intéressants à propos de ce type est qu'il offre un accès aux données de `𝛰(1)`. La bibliothèque offre les deux types d'accesseurs _safe_ et _unsafe_ comme pour les _lists_ vues précédemment.
527
+
528
+
Voici un exemple d'un _container_ qui nous permet de stocker et récupérer les caractères _ascii_ à partir de leur code.
529
+
530
+
__Note__: Vous pouvez installer la biblithèques `vector` dans votre interpréteur _ghci_ grâce aux commandes : `cabal repl --build-depends "vector"` ou `stack exec --package vector -- ghci`
531
+
532
+
```haskell
533
+
ghci> import Data.Vector as V
534
+
ghci> asciiChars =V.fromList ['\NUL'..'\DEL']
535
+
ghci> asciiChars !48
536
+
'0'
537
+
ghci> asciiChars !97
538
+
'a'
539
+
ghci> asciiChars !65
540
+
'A'
541
+
ghci> asciiChars !?65
542
+
Just'A'
543
+
ghci> asciiChars !?128
544
+
Nothing
545
+
ghci> asciiChars !?127
546
+
Just'\DEL'
547
+
```
548
+
549
+
Ils offrent également une capacité à subdiviser un _vector_ en plusieurs autres de manière performante `𝛰(1)`. la fonction `slice` prend un index de départ, la longueur voulue et le _vector_ à subdiviser, elle retourne le nouveau _vector_. Cette fonction est _unsafe_ : si l'index de départ additionné à la longueur demandée donne un résultat supérieur à la longueur du _vector_ une erreur aura lieu à l'exécution (_runtime error_) !
550
+
551
+
```haskell
552
+
ghci>:t V.slice
553
+
V.slice::Int->Int->Vectora->Vectora
554
+
ghci> lowerCase =V.slice 9726 asciiChars
555
+
ghci> lowerCase
556
+
"abcdefghijklmnopqrstuvwxyz"
557
+
ghci> upperCase =V.slice 6526 asciiChars
558
+
ghci> upperCase
559
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
560
+
ghci> nums =V.slice 4810 asciiChars
561
+
ghci>V.length nums
562
+
128
563
+
ghci> nums
564
+
"0123456789"
565
+
-- Error case, the asciiChars vectors has length 128, and our slice supposes a
error, called at ./Data/Vector/Internal/Check.hs:87:5 in vector-0.12.3.0-8cc976946fcdbc43a65d82e2ca0ef40a7bb90b17e6cc65c288a8b694f5ac3127:Data.Vector.Internal.Check
571
+
```
572
+
573
+
## Overloaded Lists
574
+
575
+
Vous aurez noté que l'on utilise souvent la fonction `fromList` pour construire nos _containers_. Il y a une extension (`OverloadedLists`) qui permet d'utiliser la syntaxe de création des _lists_. L'inconvénient est que si le type n'est pas explicitement fournit les messages d'erreur ne seront pas précis.
576
+
577
+
```haskell
578
+
ghci> :set -XOverloadedLists -- This is the language extension
579
+
ghci> [1,2,3] :: Set Int
580
+
fromList [1,2,3]
581
+
ghci> [1,2,3] :: Vector Int
582
+
[1,2,3]
583
+
ghci> [('a', 1),('b', 2),('c', 3)] :: Map Char Int
584
+
fromList [('a',1),('b',2),('c',3)]
585
+
```
586
+
587
+
Si on n'explicite pas le type voulu...
588
+
589
+
```haskell
590
+
ghci> ["1", "2", "3"]
591
+
592
+
<interactive>:11:1: error:
593
+
• Illegal equational constraint GHC.Exts.Item l ~ [Char]
594
+
(Use GADTs or TypeFamilies to permit this)
595
+
• When checking the inferred type
596
+
it :: forall {l}.
597
+
(GHC.Exts.IsList l, GHC.Exts.Item l ~ [Char]) =>
598
+
l
599
+
```
600
+
601
+
L'erreur est particulièrement peut explicite, c'est pourquoi cette extension n'est pas activée par défaut. C'est toujours bon à savoir !
0 commit comments