Formation F#
  • Intro
  • Bases
    • Le F♯, c'est quoi ?
    • Syntaxe
    • Premiers concepts
    • 🍔 Quiz
  • Fonctions
    • Signature
    • Fonctions
    • Fonctions standard
    • Opérateurs
    • Fonctions : compléments
    • 🍔 Quiz
    • 📜 Récap’
  • Types composites
    • Généralités
    • Tuples
    • Records
    • Unions
    • Enums
    • Records anonymes
    • Types valeur
    • 🍔 Quiz
  • Types : Compléments
    • Type unit
    • Génériques
    • Types flexibles
    • Unités de mesure
    • Conversion
    • Exceptions F#
  • Pattern matching
    • Patterns
    • Match expression
    • 🚀 Active Patterns
    • 📜 Récap’
  • Collections
    • Vue d'ensemble
    • Types
    • Fonctions génériques
    • Fonctions spécifiques
    • 🍔 Quiz
    • 📜 Récap’
  • Programmation asynchrone
    • Workflow asynchrone
    • Interop avec la TPL .NET
    • 📜 Récap’
  • Types monadiques
    • Type Option
    • Type Result
    • Smart constructor
    • 🚀 Computation expression (CE)
    • 🚀 CE - Fondements théoriques
    • 📜 Récap’
  • Module & namespace
    • Vue d'ensemble
    • Namespace
    • Module
    • 🍔 Quiz
    • 📜 Récap’
  • Orienté-objet
    • Introduction
    • Membres
    • Extensions de type
    • Classe, structure
    • Interface
    • Expression objet
    • Recommandations
  • 🦚 Aller plus loin
Propulsé par GitBook
Sur cette page
  • Réponses
  • Composition de types
  • Création de nouveaux types ?
  • ❓ Combiner 2 Unions ?
  • 💡 Extension d'un Record
  • Conclusion

Cet article vous a-t-il été utile ?

Modifier sur GitHub
  1. Types composites

🍔 Quiz

Relier types et concepts :

type Color1 = int * int * int
type Color2 = Red | Green | Blue
type Color3 = Red=1 | Green=2 | Blue=3
type Color4 = { Red: int; Green: int; Blue: int }
type Color5 = {| Red: int; Green: int; Blue: int |}
type Color6 = Color of Red: int * Green: int * Blue: int
type Color7 =
    | RGB of { Red: int; Green: int; Blue: int }
    | HSL of { Hue: int; Saturation: int; Lightness: int }

// A. Alias
// B. Enum
// C. Record
// D. Record anonyme
// E. Single-case union
// F. Union
// G. Union enum-like
// H. Tuple

💡 Plusieurs choix possibles

Réponses

Types
Concepts

type Color1 = int * int * int

H. Tuple + A. Alias

type Color2 = Red ∣ Green ∣ Blue

G. Union enum-like

type Color3 = Red=1 ∣ Green=2 ∣ Blue=3

B. Enum

type Color4 = { Red: int; Green: int… }

C. Record

type Color5 = {∣ Red: int; Green: int… ∣}

D. Record anonyme + A. Alias

type Color6 = Color of Red: int * …

E. Single-case union + H. Tuple

type Color7 = RGB of { Red: int… } ∣ HSL…

F. Union + C. Record

Composition de types

Création de nouveaux types ?

  • ❌ Les types algébriques ne supportent pas l'héritage de classe.

    • Ils ne peuvent pas hériter d'une classe de base.

    • Ils sont sealed : on ne peut pas en hériter.

    • Mais ils peuvent implémenter des interfaces.

  • ✅ Les types algébriques sont créés par composition, sous forme de :

    • Agrégation dans un product type (Record, Tuple)

    • "Choix" dans un sum type (Union)

❓ Combiner 2 Unions ?

Considérons les 2 types Union ci-dessous :

type Noir = Pique | Trefle
type Rouge = Coeur | Carreau

Comment les combiner pour avoir un objet qui soit au choix Pique, Trefle, Coeur ou Carreau ?

  • Par aplatissement un peu comme en TypeScript ?

type CouleurKo = Noir | Rouge

❌ Noir (comprendre CouleurKo.Noir) est un case de l'union CouleurKo totalement décorrélé du type Noir. F# permet de les nommer pareil mais c'est malencontreux ici.

  • Par composition ?

type Couleur = Noir of Noir | Rouge of Rouge
let pique = Noir Pique

✅ Un peu verbeux mais cela marche

  • Par création d'une toute nouvelle Union ?

type Couleur = Pique | Trefle | Coeur | Carreau
let pique = Pique

☝ On peut passer par des fonctions pour convertir explicitement chaque cas entre eux :

type Noir = Pique | Trefle
type Rouge = Coeur | Carreau

type Couleur =
    | Pique | Trefle | Coeur | Carreau

    static member ofNoir noir =
        match noir with
        | Noir.Pique -> Couleur.Pique
        | Noir.Trefle -> Couleur.Trefle

    static member ofRouge rouge =
        match rouge with
        | Rouge.Coeur -> Couleur.Coeur
        | Rouge.Carreau -> Couleur.Carreau

let coeur = Couleur.ofRouge Rouge.Coeur

💡 Extension d'un Record

Il existe une autre manière de créer un type à partir d'un autre type en procédant par extension. → Il est possible de créer à la volée un Record anonyme qui étend un Record existant, en partant d'une instance de ce Record et en lui ajoutant des champs :

type Person = { Name: string; City: string }
let joe = { Name = "Joe"; City = "Paris" }
let joeWithZip = {| joe with Zip = 75001 |}
(*
val joeWithZip: {| City: string; Name: string; Zip: int |} = { City = "Paris"
                                                               Name = "Joe"
                                                               Zip = 75001 }
*)

❌ Par contre, on ne peut pas faire l'inverse, à savoir enlever de champs pour obtenir un type "réduit". Ce n'est pas encore supporté par F#.

Conclusion

Beaucoup de façons de modéliser !

De quoi s'adapter :

  • À tous les goûts ?

  • En fait surtout au domaine métier !

PrécédentTypes valeurSuivantType unit

Dernière mise à jour il y a 2 ans

Cet article vous a-t-il été utile ?

Intéressant pour changer de modélisation

Attention au conflit de nom sur les Cases des Unions : → Pique = Couleur.Pique ou Noir.Pique ?

✔️
⚠️