Plein de fiches de Haskell !
This commit is contained in:
parent
07e4d08e83
commit
bac1b08b30
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ test2.html
|
||||
test.c
|
||||
fichier1.txt
|
||||
levallois.jpg
|
||||
fstfunc.hs
|
||||
|
||||
*.aux
|
||||
*.log
|
||||
|
||||
47
HSK1.md
Normal file
47
HSK1.md
Normal file
@ -0,0 +1,47 @@
|
||||
# Haskell 1
|
||||
|
||||
### Exercice 1
|
||||
1. C'est un langage qui execute ses instructions de manière séquentielle. Cf cours de THprog ^^.
|
||||
2. C'est un langage qui manipule des fonctions, des objets et dont l'execution est plutôt arborescente.
|
||||
3. Dans un langage fonctionnel pur, la valeur ou état d'une variable n'est pas modifiable. L'instruction `let` n'alloue pas une case mémoire donnée au programme, mais affecte un nom à une valeur.
|
||||
4. Un langage fonctionnel pur n'a pas d'effet de bord (*side effect*). Simplement une entrée, et une sortie.
|
||||
5. C'est un paradigme différent, adapté à certains algorithmes. Les erreurs de développement sont moins fréquentes car l'objectif d'une fonction nommée est en général plus clair que celui d'une série d'instructions. (Plus pas de variable qui traine et dont la valeur est modifiée par une impromptue ligne perdue).
|
||||
|
||||
### Exercice 2
|
||||
1. L'évaluation paresseuse décrit la non execution/évaluation de segments de code dont le résultat ne sera pas utilisé. Par exemple, dans une conjonction logique, si un terme est évalué à *faux*, alors il n'est plus utile d'évaluer les autres.
|
||||
2. Le programme évalue d'abord addTwo(4) -> 6.
|
||||
Puis il peut ensuite évaluer addTwo(addTwo(4)) -> addTwo(6) -> 8.
|
||||
Enfin, il peut évaluer addTwo(addTwo(addTwo(4))) -> addTwo(8) -> 10.
|
||||
3. Le typage statique signifie qu'une variable du code a un et un seul type qui lui est assigné par le compilateur. Cela permet de ne pas confondre les variable et de ne pas effectuer d'opération illégales car fausses par maladresse (ajouter un entier et une chaine de caractère est souvent signe de code non intentionnel).
|
||||
4. Cela signifie que le compilateur va essayer de comprendre les types des variables utilisées de lui-même, en utilisant le contexte et les types connus. Par exemple, si l'expression `7+x` est présente, le compilateur va associée à la variable `x` le type «entier».
|
||||
|
||||
Ça évite d'avoir à préciser tous les types, ce qui peut être redondant, notamment dans les fonctions manipulant de nombreuses variables.
|
||||
5. Le compilateur devrait comprendre que `a` est de type «entier» par inférence de type justement.
|
||||
|
||||
### Exercice 3
|
||||
1. Haskell a d'autres compilateurs, comme l'`UHC` ou le `LHC`.
|
||||
2. J'installe Haskell.... AH. 1Go d'installation. Je vais faire le reste des questions ...
|
||||
3. La plateforme Haskelle contient:
|
||||
- GHC le compilateur
|
||||
- Cabal le gestionnaire de paquets Haskell
|
||||
- Stack un outil aidant au développement de projets Haskell.
|
||||
- haskell-language-server une api permettant d'utiliser Haskell dans son IDE favori.
|
||||
4. Le mode interactif de GHC permet d'évaluer des expression Haskell de manière interactive, plutôt que de compiler puis executer l'intégralité du programme. C'est utile pour deboguer un programme, ou jouer avec/tester les fonctionnalités de Haskell.
|
||||
5. Pour lancer GHCi, il faut taper la commande .... `ghci`.
|
||||
6. Pour quitter, on peut lancer le caractère `EOF`, typiquement avec Ctrl+D.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
41
HSK2.md
Normal file
41
HSK2.md
Normal file
@ -0,0 +1,41 @@
|
||||
# Haskell 2
|
||||
|
||||
### Exercice 1
|
||||
```
|
||||
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
|
||||
Prelude> 2+5
|
||||
7
|
||||
Prelude> 5/2
|
||||
2.5
|
||||
Prelude> 2^4
|
||||
16
|
||||
Prelude> -3
|
||||
-3
|
||||
Prelude> 2 + -3
|
||||
|
||||
<interactive>:5:1: error:
|
||||
Precedence parsing error
|
||||
cannot mix ‘+’ [infixl 6] and prefix `-' [infixl 6] in the same infix expression
|
||||
Prelude> 2 + (-3)
|
||||
-1
|
||||
Prelude> 2-3
|
||||
-1
|
||||
Prelude>
|
||||
```
|
||||
|
||||
Haskell ne comprend pas `2 + - 3` car `-` et `+` ont la même précédence, et que dans ce cas, les instructions sont lues de gauche à droite, et lorsque le compilateur trouve `-` comme second terme de l'additon, il se plaint que ce n'est pas un nombre.
|
||||
|
||||
### Exercice 2
|
||||
1. Non, le parenthesage impose au calcul `2+4` de se faire avant, contredisant la précédence plus élevée du `*`.
|
||||
2. Il y a 10 niveaux, de 1 à 9.
|
||||
3. Le niveau de précédence est indiqué à la toute fin après `infixl`.
|
||||
4. Pas le même résultat, l'opérateur `^` est infixe *à droite* contrairement à plus et moins qui sont infixes *à gauche*.
|
||||
5. `(^)` est donc associatif à droite.
|
||||
6. La direction de l'associativité est donnée en bas du `:info` : `infixl` pour une associativité à gauche et `infixr` pour une associativité à droite.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
16
HSK3.md
Normal file
16
HSK3.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Haskell 3
|
||||
|
||||
### Exercice 1
|
||||
1. Attention, révolution dans la science informatique. En effet ! Haskell prend une position assez précaire en définissant le type booléen avec non pas un, non pas trois, mais deux valeurs ! Veuillez applaudir Messieurs et Mesdames : `True` et `False`.
|
||||
|
||||
2. Ben ... Elles fournissentTrue || (True && False) le résultat attendu (avec une précédence plus élevée pour le `not`, et égale entre `&&` et `||`.
|
||||
3. L'expression `True && 1` est invalide car `True` est un booléen et `1` est un entier (c'est bien le typage fort).
|
||||
|
||||
### Exercice 2
|
||||
1. L'opérateur `==` compare deux valeurs et renvoie `True` si elles sont égales, `False` sinon.
|
||||
2. Les autres opérateurs sont `<` «plus petit que», `<=` plus petit ou égal à, `>` et `>=` les symetriques des deux précédents et `/=` différent de.
|
||||
3. Les opérateurs ont l'effet attendu.
|
||||
4. Tous ces opérateurs ont la même précédence (4).
|
||||
5. Non c'est incorrect car ils ont tous la même précédence.
|
||||
6. Une bonne écriture serait `(1==2)/=(1==1)`
|
||||
|
||||
39
HSK4.md
Normal file
39
HSK4.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Haskell 4
|
||||
|
||||
### Exercice 1
|
||||
1. La commande crée une liste d'entiers de longueur 4.
|
||||
2. La commande crée une liste de chaine de caractères de longueur 4.
|
||||
3. La commande crée une erreur car une liste ne peut pas être fait d'objets de type différent (ici chaine de caractère et caractère seul).
|
||||
4. La commande crée une liste vide n'ayant encore aucun type (polymorphisme).
|
||||
5. La commande crée une erreur pour les même raisons que 3.
|
||||
6. La commande crée la liste [11,1]. Haskell évalue bien le contenu de la liste pour l'afficher.
|
||||
|
||||
### Exercice 2
|
||||
1. On ajoute un élément grâce à l'opérateur `:` (lu *cons*).
|
||||
2. Les listes en Haskell sont chainées. Donc `cons` est un constructeur du type `List`.
|
||||
3. Par exemple `3:[4,5]` crée la liste [3,4,5].
|
||||
4. Il faut utiliser l'opérateur `++`.
|
||||
5. Il prend une liste à gauche et une liste à droite et renvoie ... la concaténation des deux listes.
|
||||
6.
|
||||
```
|
||||
Prelude> [2,9,4]++[4,7]++[]
|
||||
[2,9,4,4,7]
|
||||
```
|
||||
8. Il faut utiliser l'opérateur `!!`
|
||||
9. Il prend une liste à gauche et un entier à droite, l'indexation commencant à 0. On execute la commande suivante : `[4,56,76,8,999,78] !! 3`
|
||||
|
||||
### Exercice 3
|
||||
1. Crée une liste de listes d'entiers.
|
||||
2. Assigne à la lettre `l` la valeur donnée.
|
||||
3. Affiche la valeur associée à la lettre `l`
|
||||
4. Affiche la liste associée à `l` accolée à la liste indiquée. `l` n'est pas modifiée.
|
||||
5. Affiche la liste associée à `l` à laquelle on a apposée comme premier élément la liste «singleton -99».
|
||||
6. Affiche le troisième élément de la liste associée à la lettre `l`.
|
||||
### Exercice 4
|
||||
Ces commandes donnent le résultat escompté en utilisant l'ordre lexicographique sur les listes.
|
||||
|
||||
### Exercice 5
|
||||
1. Crée la liste des entiers de 1 à 10 inclus.
|
||||
2. Crée la liste arithmétique commencant par 1.0, puis 1.5 et terminant par 3.0.
|
||||
3. Crée la liste arithmétique commençant par 3 puis 6 et ne contenant pas de nombre strictement plus grand que 16.
|
||||
4. Crée la liste arithmétique commençant par 15 puis 14 et ne contenant pas ne nombre strictement inferieur à 4.
|
||||
17
HSK5.md
Normal file
17
HSK5.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Haskell 5
|
||||
|
||||
### Exercice 1
|
||||
1. `'t'` correspond au caractère `t`
|
||||
2. `'test'` correspond au caractère `test` ce qui n'existe pas -> Ça plante.
|
||||
3. `['t','e','s','t']` correspond au tableau de caractères, ou «chaine de caractères» `test`
|
||||
4. `['a'..'f']` correspond au tableau de caractère contenant dans l'ordre les caractères de `a` à `f`
|
||||
5. `['a','c'..'l']` correspond au tableau de caractère contenant dans les caractères de `a` à `l` avec `c` en deuxième caractère (donc toutes les deux lettres).
|
||||
6. `'a'=='A'` renvoie `False` car `a` et `A` ne sont pas les mêmes caractères.
|
||||
7. `['a','3']` à l'instar du point 3., cela crée la chaine de caractères contenant deux caractères: `a` et `3`.
|
||||
8. `['a',3]` correspond à un tableau inhomogène.
|
||||
|
||||
### Exercice 2
|
||||
1. Les chaines de caractères sont des tableaux d'entiers.
|
||||
2. `["tata","toto","tutu"]` est donc un tableau de tableaux de caractères (un tableau 2D !)
|
||||
3. `"le "++"chien est blanc"` concatène les deux chaines de caractères.
|
||||
4. `"B"++"onjour, je m'appelle Vincent"` corrige la faute.
|
||||
7
HSK6.md
Normal file
7
HSK6.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Haskell 6
|
||||
|
||||
### Exercice 1
|
||||
1. `('a',34)` renvoie un couple du type `char*int`
|
||||
2. `['a',34]` n'est pas valide car cette expression n'est ni du type `char list` ni du type `int list`.
|
||||
3. `[(1,34),(1,45,4)]` est invalide, car cette expression n'est ni du type `(int*int) list` à cause du deuxième élément, ni du type `(int*int*int) list` à cause du premier.
|
||||
4. `("Jean","Dupond",42)` permet de stoquer telle information, qui est alors du type `(char list)*(char list)*int`.
|
||||
65
HSK7.md
Normal file
65
HSK7.md
Normal file
@ -0,0 +1,65 @@
|
||||
# Haskell 7
|
||||
### Exercice 1
|
||||
1. Houla. On peut définir une fonction comme une relation binaire fonctionelle, c'est à dire une partie de X*Y telle pour tout x dans X, y y' dans Y, x en relation avec y et x en relation avec y' implique y=y'.
|
||||
|
||||
Sinon, on peut définir une fonction comme étant un «mapping», un boîte qui à un élément de l'entrée associe un élément de la sortie. C'est aussi un morphisme d'ensembles du point de vu de la théorie des catégories.
|
||||
|
||||
2. La fonction sort a pour entrée une `int list` et pour sortie aussi une `int list`. La fonction renvoie alors la liste ordonée ayant exactement les même éléments que son entrée.
|
||||
|
||||
3. `(+) 3 4` appelle la fonction `(+)` (version préfixée de `+`) de type `int -> int -> int` en lui envoyant l'entier `3` (qui renvoie une fonction du type `int -> int`) et appliquant ce résultat à l'entier `4`.
|
||||
|
||||
4. On peut conclure .... que les opérateurs ne sont que des écritures infixées de fonctions et n'ont pas d'autre différence fondamentale. Il en va de même pour tout ce qu'on a vu: `-`,`*`, mais aussi `++`.
|
||||
|
||||
### Exercice 2
|
||||
|
||||
1. Le texte `Prelude` dans l'invite de commande GHCi indique ce qui est chargé avant l'évaluation d'expressions Haskell. Par défaut, il y a uniquement un seul module, appelé `Prelude` contenant les opérations de base.
|
||||
2. Avec un prélude vide, pour appeler les fonctions disponibles, on peut donner leur nom complet, c'est à dire avec le nom du module les englobant. Par exemple `Data.List.sort`.
|
||||
|
||||
On peut aussi appeler `import Nom.Du.Module` afin de l'ajouter au prélude et d'ainsi pouvoir ignorer le nom complet et indiquer uniquement le nom de la fonction.
|
||||
|
||||
|
||||
3. `Prelude Data.List> mod 4 3`
|
||||
4. `Prelude Data.List> even 42`
|
||||
5. `Prelude Data.List> gcd 18 12`
|
||||
6. `Prelude Data.List> head [2,56,4,9]`
|
||||
7. `Prelude Data.List> last [2,56,4,9]`
|
||||
8. `Prelude Data.List> tail [2,56,4,9]`
|
||||
9. `Prelude Data.List> length [2,56,4,9]`
|
||||
10. `Prelude Data.List> reverse [2,56,4,9]`
|
||||
11. `Prelude Data.List> maximum [2,56,4,9]`
|
||||
12. `Prelude Data.List> elem 3 [2,56,4,9]`
|
||||
13. `Prelude Data.List> concat [[5,7],[67,87]]`
|
||||
14. `Prelude Data.List> take 3 [2,56,4,9]`
|
||||
15. `Prelude Data.List> drop 2 [2,56,4,9]`
|
||||
16. `Prelude Data.List> fst (45,"Orleans")`
|
||||
17. `Prelude Data.List> snd (45,"Orleans")`
|
||||
|
||||
### Exercice 3
|
||||
1. `Prelude> :load fstfunc.hs`
|
||||
2. `*Main> addTwo 3`
|
||||
3. Cette fonction peut prendre en entrée tout type étant une instance de la classe `Num`, à savoir `Word`, `Integer`, `Int`, `Float` et `Double`.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
15
HSK8.md
Normal file
15
HSK8.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Haskell 8
|
||||
|
||||
1. Les chaines de caractères sont des listes de caractères.
|
||||
2. Une liste a un seul type d'élément mais on peut rajouter des éléments en tête. Un tuple peut être constitué de variables de types différents, mais ne peut pas être agrandi.
|
||||
3. Les tuples sont intérésants si on souhaite manipuler un jeu de données «en bloc».
|
||||
4. (Un `s` s'est transformé en `d`). `sort` s'applique à une list et renvoie une liste contenant les mêmes éléments, mais dans l'ordre. `fst` prend en entrée un tuple, et renvoie le premier élément du tuple.
|
||||
5. `sort` fonctionne pour des listes dont le type d'éléments étend la classe `Ord` (donc pas tous).
|
||||
6. Dans ce code, `y` a dans le corps du `let` pour valeur `3`, le corps étant la partie `y+4`.
|
||||
7. Cette expression correspond à la chaine de caractères `"dg"` (une liste de deux éléments).
|
||||
8. L'expression indiquée renvoie un booléen de type `Bool`.
|
||||
9. `sort` est une fonction alors que `:` est un constructeur. Une application pratique est que l'on peut faire du *pattern matching* sur `:` mais pas sur `sort`.
|
||||
10. `map (*2) [1,4,7]` applique la fonction *multiplier par deux* à la liste donnée, ce qui renvoie la liste `[2,8,14]`.
|
||||
11. `let addTwo=(+2) in addTwo 4` ou `let addTwo y = y+2 in addTwo 4`.
|
||||
12. Dans cette expression, le pattern est `(t,q)` qui *match* n'importe quel tuple de 2 éléments (ou *2uplet* ou *paire*).
|
||||
13. Ces deux expression renvoient la même valeur, puisque le type des listes est défini de manière inductive, `a:_:_:_` est une simplification syntaxique pour `a:(_:(_:_))`.
|
||||
21
HSK9.md
Normal file
21
HSK9.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Haskell 9
|
||||
|
||||
### Exercice 1
|
||||
1. Le typage statique permet d'éviter certaines erreurs de programmation en les capturant dès la compilation (comme ajouter un entier et une chaine de caractères par exemple).
|
||||
2. Y a des choses non typées en Haskell ? À la limite les commandes de l'interpréteur.
|
||||
3. `:t 'a'` affiche le type de l'objet `'a'`, c'est à dire `Char`.
|
||||
4. L'opérateur `::` signifie ici *est du type*
|
||||
5. `Int` est un entier machine, de 32 ou 64 bits typiquement. `Integer` est un entier mathématique *théoriquement* non borné.
|
||||
6. Cette différence permet de coder des algorithmes «machine» comme les codages binaires, les opérations bit à bit, et les entiers `Integer` permettent de coder sans se soucier de dépassement de la capacité de l'entier, qui peut amener des bugs plutôt étranges. De telles considérations peuvent simplifier les preuves d'algorithme.
|
||||
7. Haskell prévoit les types `Double` et `Float` pour représenter les réels, respectivement sur 64 et 32 bits.
|
||||
8. Les booléens sont appelés `Bool`.
|
||||
9. Les caractères sont appelés `Char`.
|
||||
|
||||
### Exercice 2
|
||||
|
||||
1. Un type explicite est un type donné ... explictiement à une variable, sans le déduire du contexte.
|
||||
2. `True` est du type `Bool` (c'est un booléen).
|
||||
3. `"string` est du type `[Char]` (une liste de caractères)
|
||||
4. `('e', False)` est du type `(Char, Bool)` (un 2-uplet avec un caractère en premier élément et un booléen en second élément).
|
||||
5. Les types de ces trois variables sont différents. Certes ils sont tous des tuples, mais *tuple* est une classe de types. Le premier est un tuple `(Char, Bool)`, le second un tuple `([Char], Bool)` et le dernier un tuple `(Char, Bool, [Char])`.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user