29 février 2016 - Groupe .NET/ASP.NET
Sujet: F#
Conférencier: Kevin Olivier Avignon
Pour ceux qui ne le connaissent pas, F# fait parti des langages .NET les plus récents du monde .NET. Il tire ses racines principalement du langage OCaml. Il ne faut pas se méprendre sur sa nature; il ne s'agit pas d'un langage purement fonctionnel. F# est en fait un langage hybride dans lequel il est possible de s'exprimer de façon impérative ou aussi, avec des objets. La présentation introduira comment s'immerger dans la pensée fonctionnelle et bâtir des applications avec les rudiments de F#.
3. Qui suis-je ?
◦ Étudiant en génie des technologies de l’information (ÉTS)
◦ Stagiaire C# & F# en systèmes distribués chez Genetec
4. Contenu de la présentation
1. Qu’est-ce que le paradigme fonctionnel ?
2. Pourquoi s’intéresser à F# ?
3. Les rudiments de F#
4. Éléments clés de la pensée fonctionnelle
5. Domaines d’application pour F#
6. Qu’est-ce qu’un paradigme de programmation ?
Style de programmation permettant de solutionner un problème informatique à
l'aide d'un langage (ex: C#, F#, VB.NET)
Exemples de paradigmes connus:
Procédurale (routine): Une série d’étapes à réaliser
Orienté-objet : Une collection d’objets en perpetuelle intéraction
7. Paradigme fonctionnel
Une suite de fonctions mathématiques sans états
Une fonction mathématique est
Une expression (un algorithme avec ses entrées/sorties)
Générale
Sujet à réduction jusqu’à être irréductible
Les fonctions mathématiques n’admettent pas
8. Pourquoi s’y intéresser?
Le code est plus simple à gérer (aucun état)
Une gestion de la concurrence sans soucis
Les programmes sont généralement plus courts
10. General Purpose Language
F# est un langage de .NET, tout comme C# et VB.NET
Il est en mesure de répondre à une variété de problèmes en tout genre
S’intégre dans une solution .NET existante
Peut être exploité pour écrire de l’orienté-objet, impératif, fonctionnel ou autre
11. Des solutions simples pour des problèmes
complexes
F# est concis et très expressif.
Moins de code nécessaire à lire et maintenir
Les fonctions de haut niveau encourage la réutilisabilité
12. FSI
Outil permettant d’exécuter le code F# sans passer par debug
C’est un interpreteur à l’intérieur d’un command prompt
Permet également d’écrire du code pendant l’exécution
Pour être utiliser avec Visual Studio
Ctrl+Alt+F
Clique droit + Option Execute in Interactive
Chaque instruction doit être compléter avec “;;” au lieu d’un dans FSI
13. Justesse du code
Les valeurs(pas de variables) sont immuables par défaut
Immuabilité : L’état de la valeur ne peut être modifié après son attribution
Un système de type de données stricte
Autant votre pire ennemi que votre meilleur ami
Du pattern matching très flexible et exhaustif
14. Pattern matching
Définition : Une solution flexible pour modifier les données selon des règles spécifiques (patterns)
Permet de naviguer et décomposer simplement dans une structure de données
Chaque pattern est examiné pour valider si c’est compatible avec la structure de données
type LeavesColor=
| Red = 0
| Green = 1
let printColorName (color:LeavesColor) =
match color with
| Color.Red -> printfn "Red"
| Color.Green -> printfn "Green"
| _ -> ()
printColorName LeavesColor.Red
printColorName LeavesColor.Green
15. Aucun NullReferenceException
Option type
Type polymorphique encapsulant une valeur optionnelle
S’il y a une valeur à retourner -> Some<T>
Sinon -> None
N’est jamais à l’état null
Semblable aux nullables
let compute = function
| None -> "No value"
| Some x -> sprintf "The value is: %d" x
printfn "%s" ( Some 42 |> compute)(* The value is: 42 *)
printfn "%s" (compute None) (* No value *)
16. Type inference par défaut
Avec C#, c’est fait en ayant recours au keyword var afin d’augmenter la lisibilité
Dictionary<List<SomeObject>,string[]> maVariable = new
Dictionary<List<SomeObject>,string[]>();
var maSecondeVariable = new Dictionary<List<SomeObject>,string[]>();
Le compilateur est intelligent et déduit rapidement le type exact d’une valeur
L’information est déduite selon le contexte
S’il manque d’information, il faut lui en donner davantage sinon la solution ne “build”
pas
let f a b = a + b + 100 //Retourne une valeur de type uint32 (int)
17. Moins de bugs
Système de type strict
Utiliser des Option types
Type inference
Immuabilité
Unit of Measures (custom unit)
[<Measure>] type foot
let distance = 3.0<foot>
// type inference for result
let distance2 = distance * 2.0
19. let bindings
Keyword très puissant permet de :
Faire du value binding ou attribuer une valeur à un symbol (nom de variable)
Déclarer une fonction
Déclarer une valeur locale/globale
Déclarer une valeur mutable
20. Control flow - les if
C’est une structure if-then-else
Ce sont des expressions avec des branches de types équivalentes
Mieux vaut utiliser le pattern matching que if dans certains cas
// bad
let badF x =
if x = 1
then "a"
else "b"
// best
let bestF x =
match x with
21. Control flow - Les boucles
Comme la structure conditionnelle if, les boucles conservent une structure familière
Il s’agit malgré tout d’expressions
Les boucles retournent le type unit
S’apparent à void
C’est une absence de valeur représenté par ()
Les do binding demeurent locaux
Retournent également unit
22. Control flow - for loop
La boucle for a la structure suivante :
for start - to | downto - do
body-expression
Exemple:
let f =
for i in [1..10] do
i + i |> ignore
let newF =
for i=10 downto 1 do
i + i |> ignore
23. Control flow - foreach
La boucle foreach a la structure suivante :
for pattern in enumerable-expression do
body-expression
// Looping over a list.
let list1 = [ 1; 5; 100; 450; 788 ]
for i in list1 do
printfn "%d" i
24. Control flow - while loop
La boucle while a la structure suivante :
while test expression do
body-expression
let lookForValue value maxValue =
let mutable continueLooping = true
let randomNumberGenerator = new Random()
while continueLooping do
// Generate a random number between 1 and maxValue.
let rand = randomNumberGenerator.Next(maxValue)
printf "%d " rand
if rand = value then
printfn "nFound a %d!" value
25. Pipeline Operators
Pipe-forward operator ( |> )
Permet de passer une valeur intermédiaire à une fonction
Définit comme let (|>) f x = f x
[1..2..40] List.filter (fun value -> value %2 =0) |> printfn
Foward composition operator ( >> )
Permet de composer la fonction f dans la fonction g
Se définit comme let ( >> ) f g x = g (f x )
Pipe-backward operator ( <| )
26. Array, List & Seq
Il s’agit des Collection types les plus importants et utilisés en F#
Array est une mutable collection ayant une taille fixe avec un 0 based index
let array1 = [| 1; 2; 3 |]
List est une collection immuable d’éléments ordonnés du même type
let list123 = [ 1; 2; 3 ]
Seq ou Sequence, est un équivalent à IEnumerable<T>
Tous les structures .NET dérivant de IEnumerable peuvent être des Seq
Il est possible de passer de l’un à l’autre en faisant
CollectionType.toArray|toList|ToSeq
27. Tuples
Un regroupement de données pouvant être de type différent
(1,2) // Tuple de int, int
(1, “one”) Tuple de int, string
(1, 2.0, “three”, 3+1) //Tuple de int, float, string, expression
Donne une solution pour retourner plusieurs valeurs dans une fonction
28. Discriminated Unions
Permettent de rapidement prototyper un domaine d’affaires
Un ensemble de types hétérogènes
Les bons types de données
Les types non valides
Exemple :
type FormeGeometrique =
| Rectangle of longeur : int * largeur:int
|Cercle of int
29. Records
Sont immuables par défaut
Le record peut être mise à jour en faisant une copie et modifiant un champ spécifique
Se différencient des classe en orienté-objet
Sont seulement des propriété exposées
N’ont aucun constructeur
type Point3D = { x: float; y: float; z: float }
let evaluatePoint (point: Point3D) =
match point with
| { x = 0.0; y = 0.0; z = 0.0 } -> printfn "Point is at the origin."
| { x = xVal; y = 0.0; z = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal
| { x = 0.0; y = yVal; z = 0.0 } -> printfn "Point is on the y-axis. Value is %f." yVal
| { x = 0.0; y = 0.0; z = zVal } -> printfn "Point is on the z-axis. Value is %f." zVal
30. Modules
Un regroupement logique du code tout comme un namespace
Un fichier est mis par défaut dans un module si rien n’est spécifié
S’apparente à une classe statique
33. Les fonction sont les first citizens
C’est le paradigme fonctionnel, il est normal de prioriser les fonctions
Il faut voir une fonction comme étant un objet mathématique
Système dynamique et souple
Il est possible de passer une fonction comme un input
Il est possible de retourner une fonction comme output
34. Préserver les états orignaux
En manipulant un Collection type (list)
Penser à conserver son état original
C’est une entité à manipuler avec soin
Copier l’entité au besoin
Renforcer l’immuabilité dans vos programmes
Moins de bugs
35. Éviter la mutabilité
Permet d’éviter les side-effects
Les valeurs ne sont pas modifier après leur évaluaion
Rend le code thread-safe
S’assure qu’un thread ne peut modifier la valeur pendant son cycle
Pour mettre à jour une donnée
Il suffit simplement d’en faire la copie et utiliser cette copie
Retourner des fonctions non encapsulées
36. Exploiter la récursion
La fonction s’appelle elle-même jusqu’à temps de compléter son itération
Augmente la lisibilité pour le programmeur
Réduit le code
Engendre théoriquement moins de bugs
37. Partial function application
Technique puissante
Ne pas avoir à complètement appliquer une fonction
Permet de définir une fonction à N paramètre
Obtenir le résultat final au moment voulu
let add42 = (+) 42 // partial application
add42 1
add42 3
38. S’éloigner de la mentalité OO
Cesser de penser en classe et exploiter
Records
Discriminated Unions
Cesser de penser aux méthodes à encapsuler
Créer des high order functions
L’héritage n’a plus sa place ici
Penser plutôt au partial function application
39. Pattern matching > if structure
Permet de valider tous les cas possibles
Le compilateur mentionne si une situation a été oublié
Rend les cas à traiter plus simples à comprendre
Structure avec moins de “bruit”
41. Domaines d’applications
1. L’apprentissage machine
2. L’analyse de données
3. L’actuariat
4. Le développement web (WebSharper)
5. Le développement mobile (Xamarin)
6. Le traitement vidéo avec le GPU