Track
/
Elm
Elm
/
Esercizi
/
Biglietto, prego!
Biglietto, prego!

Biglietto, prego!

Esercizio di apprendimento

Introduzione

Pattern matching

Il pattern matching permette di scrivere codice con diramazioni espressive e la destrutturazione consente un'elegante associazione di valori alle variabili.

Pattern matching semplice

Il pattern matching può associare valori a variabili, oppure scartarli con il carattere jolly _, con l'uso dell'istruzione 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!"

Destrutturazione

La destrutturazione può associare valori nei binding let, negli argomenti di una funzione e, naturalmente, nelle espressioni case, ogni volta che per i dati è possibile una sola forma.

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 destrutturazione può essere usata anche con i record, oppure con la parola chiave 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

Istruzioni

Fai parte dell'helpdesk IT e vuoi rendere il sistema di ticketing più efficiente e fornire statistiche al tuo manager.

Un ticket ha uno stato (new, in progress...), un creatore (identificato da un nome utente e da un ID dipendente), può essere assegnato a un dipendente IT e contiene una cronologia di commenti.

Ecco quattro attività che miglioreranno l'attuale sistema di ticketing.

1. Rilevare i commenti vuoti

I commenti vuoti ingombrano l'interfaccia e non portano alcuna informazione: vuoi eliminarli.

Definisci una funzione ausiliaria emptyComment che prende una coppia utente/commento e restituisce True per i commenti vuoti.

Usa la destrutturazione per estrarre l'utente e il commento direttamente nell'argomento della funzione. Ignora l'utente, dato che quell'informazione non ti serve.

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

2. Contare il numero di commenti del creatore

Il tuo manager vuole avere statistiche sul coinvolgimento degli utenti nel processo di gestione dei ticket. Ti chiede di verificare quanti commenti sono stati aggiunti dal creatore del ticket.

Definisci numberOfCreatorComments, che prende un ticket e restituisce il numero di commenti aggiunti dal creatore del ticket.

Usa la destrutturazione nell'argomento della funzione per estrarre il record dal tipo Ticket, insieme ai campi del record che ti servono. Poi destruttura createdBy in un binding let, così da poter contare i commenti rilevanti. Usa le funzioni di List per fare il conteggio e usa la destrutturazione nell'argomento di una funzione anonima per separare la coppia utente/commento.

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

3. Rilevare i ticket assegnati al Dev Team

Alcuni ticket devono essere escalati ad Alice, Bob o Charlie del Dev Team. È importante tenerli d'occhio per assicurarsi che facciano progressi.

Definisci una funzione ausiliaria assignedToDevTeam che verifica se un ticket è assegnato a uno dei membri del Dev Team.

Usa la destrutturazione nell'argomento della funzione per estrarre il record dal tipo Ticket e anche il campo che ti serve. Poi usa un'unica istruzione case per verificare se il ticket è assegnato ad Alice, Bob o Charlie, usando il pattern matching ricorsivo per estrarre i loro nomi utente e il pattern matching letterale per riconoscerli.

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

4. Assegnare i ticket ai dipendenti IT

A volte diversi ticket devono essere riassegnati ad altri dipendenti IT.

Definisci una funzione assignTicketTo che ti aiuti a farlo. La funzione riceve due argomenti: un utente a cui assegnare il ticket e un ticket. Se lo stato del ticket è New, assegnalo al nuovo utente e cambia lo stato in InProgress. Per gli altri stati, riassegna semplicemente il ticket ai nuovi utenti, tranne per i ticket con stato Archived, che non vanno modificati affatto.

Usa la destrutturazione nell'argomento della funzione per estrarre il record dal tipo Ticket e anche il campo che ti serve, e usa anche la parola chiave as per catturare l'intero record così com'è. Usa un'unica istruzione case per fare pattern matching sullo stato e restituire il ticket appropriato, creato modificando il record originale che hai catturato con la parola chiave 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!!" ) ]
--        }
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Elm Exercism

Vuoi iniziare Biglietto, prego!?

Iscriviti a Exercism per imparare e padroneggiare Elm con 28 concetti110 esercizi e il mentoring di persone reali, tutto gratis.