Parcours
/
Elm
Elm
/
Exercices
/
Un ticket, s'il vous plaît !
Un ticket, s'il vous plaît !

Un ticket, s'il vous plaît !

Exercice d'apprentissage

Introduction

Filtrage par motif

Le filtrage par motif permet d'écrire du code dont les branchements sont expressifs, tandis que la déstructuration lie élégamment les valeurs aux variables.

Filtrage par motif simple

Le filtrage par motif permet de lier des valeurs à des variables, ou de les ignorer avec le joker _, à l'aide de l'instruction case.

type Entity = Alien | Stranger (Maybe String) | Friend { name: String }

hello : Entity -> String
hello entity =
    case entity of
        -- Custom type variant
        Alien -> "Hello, you are not from around here are you?"
        -- Binding to a litteral value nested in Stranger
        Stranger (Just nametag) -> "Hello, erm... " ++ nametag ++ "."
        -- Discarding Friend's data
        Friend _ -> "Hi!"
        -- All other cases
        _ -> "Hello stranger!"

Déstructuration

La déstructuration permet de lier des valeurs dans les liaisons let, dans les arguments d'une fonction et, bien sûr, dans les expressions case, dès lors qu'une seule forme est possible pour la donnée.

pairSum : ( Int, Int ) -> Int
pairSum pair =
    -- Destructuring of a pair in a 'let' binding
    let ( x, y ) = pair
    in x + y

-- Destructuring in the function argument
pairSum : ( Int, Int ) -> Int
pairSum ( x, y ) = x + y

-- Custom type containing a single variant
type Container = Box String

-- Destructuring in the function argument
unbox : Container -> String
unbox (Box str) = str

-- Destructuring combined with pattern matching
unboxMaybe : Maybe Container -> Maybe String
unboxMaybe maybeContainer =
    case maybeContainer of
        Nothing -> Nothing
        Just (Box "42") -> Just "The answer to the universe!"
        Just (Box str) -> Just str

La déstructuration s'utilise aussi pour les enregistrements, ou avec le mot-clé as.

type alias Circle =
    { radius : Float
    , center : ( Float, Float )
    }

perimeter : Circle -> Float
perimeter { radius } =
    2 * pi * radius

left : Circle -> Float
left { radius, center } =
    -- the pair center cannot be pattern matched directly in the function argument
    -- so we do it in a 'let' statement
    let ( x, _ ) = center
    in x - radius

-- using the 'as' keyword to bind both the fields and the whole record
smaller : Float -> Circle -> Circle
smaller reduction ({ radius } as circle) =
    if reduction < radius then
        { circle | radius = radius - reduction }
    else
        circle

Instructions

Tu fais partie du service d'assistance informatique, et tu veux améliorer le système de tickets pour le rendre plus efficace et fournir des statistiques à ta hiérarchie.

Un ticket a un statut (nouveau, en cours...), un créateur (identifié par un nom d'utilisateur et un identifiant d'employé), peut être affecté à un employé de l'informatique et contient un historique de commentaires.

Voici quatre tâches qui vont améliorer le système de tickets actuel.

1. Détecte les commentaires vides

Les commentaires vides encombrent l'interface et n'apportent aucune information ; tu veux les filtrer.

Définis une fonction auxiliaire emptyComment qui prend une paire utilisateur/commentaire et renvoie True pour les commentaires vides.

Utilise la déstructuration pour extraire l'utilisateur et le commentaire directement dans l'argument de la fonction. Ignore l'utilisateur, car tu n'as pas besoin de cette information.

emptyComment ( User "Alice", "" )
-- => True

2. Compte le nombre de commentaires du créateur

Ta hiérarchie veut des statistiques sur l'implication des utilisateurs dans le processus de traitement des tickets. Elle te demande de vérifier combien de commentaires sont ajoutés par le créateur du ticket.

Définis numberOfCreatorComments qui prend un ticket et renvoie le nombre de commentaires ajoutés par le créateur du ticket.

Utilise la déstructuration dans l'argument de la fonction pour extraire l'enregistrement du type Ticket en même temps que les champs dont tu as besoin dans cet enregistrement. Ensuite, déstructure createdBy dans une liaison let pour pouvoir compter les commentaires pertinents. Utilise les fonctions de List pour faire le comptage et la déstructuration dans l'argument d'une fonction anonyme pour séparer la paire utilisateur/commentaire.

numberOfCreatorComments
numberOfCreatorComments
    (Ticket
        { status = Closed
        , createdBy = ( User "Chiaki", 1 )
        , assignedTo = Nothing
        , comments = [ ( User "Chiaki", "Never mind, fixed it." ) ]
        }
    )
-- => 1

3. Détecte les tickets affectés à l'équipe de développement

Certains tickets doivent être escaladés à Alice, Bob ou Charlie de l'équipe de développement. Il est important de garder un œil sur eux pour s'assurer qu'ils progressent.

Définis une fonction auxiliaire assignedToDevTeam qui vérifie si un ticket est affecté à l'un des membres de l'équipe de développement.

Utilise la déstructuration dans l'argument de la fonction pour extraire l'enregistrement du type Ticket ainsi que le champ dont tu as besoin. Ensuite, utilise une seule instruction case pour vérifier si le ticket est affecté à Alice, Bob ou Charlie, en utilisant le filtrage par motif récursif pour extraire leurs noms d'utilisateur et le filtrage par motif littéral pour les reconnaître.

assignedToDevTeam
    (Ticket
        { status = InProgress
        , createdBy = ( User "Bill", 2 )
        , assignedTo = Just (User "Alice")
        , comments = [ ( User "Bill", "What's an 'undefined'?" ) ]
        }
    )
-- => True

4. Affecte les tickets aux employés de l'informatique

Il arrive qu'un ensemble de tickets doive être réaffecté à d'autres employés de l'informatique.

Définis une fonction assignTicketTo pour t'aider à le faire. La fonction reçoit deux arguments : un utilisateur à qui affecter le ticket et un ticket. Si le statut du ticket est New, affecte-le au nouvel utilisateur et change le statut pour InProgress. Pour les autres statuts, réaffecte simplement le ticket aux nouveaux utilisateurs, sauf pour les tickets dont le statut est Archived, qui ne doivent pas être modifiés du tout.

Utilise la déstructuration dans l'argument de la fonction pour extraire l'enregistrement du type Ticket ainsi que le champ dont tu as besoin, et utilise aussi le mot-clé as pour capturer l'enregistrement entier tel quel. Utilise une seule instruction case pour filtrer par motif sur le statut et renvoyer le ticket approprié, créé en modifiant l'enregistrement d'origine que tu as capturé avec le mot-clé as.

assignTicketTo (User "Danny")
    (Ticket
        { status = New
        , createdBy = ( User "Jesse", 3 )
        , assignedTo = Just (User "Alice")
        , comments = [ ( User "Jesse", "I've been waiting for 6 months!!" ) ]
        }
    )
-- => Ticket
--        { status = InProgress
--        , createdBy = ( User "Jesse", 3 )
--        , assignedTo = Just (User "Danny")
--        , comments = [ ( User "Jesse", "I've been waiting for 6 months!!" ) ]
--        }
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Elm Exercism

Prêt à commencer Un ticket, s'il vous plaît ! ?

Inscris-toi sur Exercism pour apprendre et maîtriser Elm avec 28 concepts110 exercices, et un vrai mentorat humain, le tout gratuitement.