Track
/
Elm
Elm
/
Esercizi
/
Il forziere del tesoro
Il forziere del tesoro

Il forziere del tesoro

Esercizio di apprendimento

Introduzione

Generici

Introduzione

I generici sono una funzionalità del linguaggio che permette di riutilizzare il codice. Per esempio, non dovrebbe importare quale tipo contiene un array per calcolarne la lunghezza. Ecco perché la funzione length usa un parametro di tipo generico a nella sua firma di tipo.

length : List a -> Int

Parametri nei tipi

Quando un tipo è generico rispetto a un altro tipo, usiamo un nome minuscolo per quest'altro tipo e lo chiamiamo parametro di tipo. Esempi comuni sono i tipi personalizzati List, Maybe e Result.

-- Maybe is generic over the type a
type Maybe a
    = Nothing
    | Just a

someString : Maybe String
someString = Just "hello"

someInt : Maybe Int
someInt = Just 42

Un'osservazione importante sui nomi dei parametri di tipo è che possono essere lunghi più di un carattere. L'unico vincolo è che devono essere nomi minuscoli. Perciò, quando è utile, tendiamo a dare loro nomi descrittivi.

Un tipo può essere generico rispetto a più tipi diversi, e quindi avere più parametri di tipo. In quel caso, ogni tipo indipendente riceve un nome minuscolo diverso. Essere indipendenti non impedisce che diventino lo stesso tipo, permette soltanto che siano diversi.

-- Result is generic over the types error and value
type Result error value
    = Ok value
    | Err error

Anche gli alias di tipo record possono avere parametri di tipo, anche se è meno comune.

-- Event is generic over the type a
type alias Event a =
    { at : Time
    , data : a 
    }

Parametri di tipo nelle funzioni

Dato che i tipi possono essere generici, possono esserlo anche le funzioni. Si possono scrivere funzioni che gestiscono tipi generici, come Maybe.withDefault.

withDefault : a -> Maybe a -> a
withDefault default maybe =
    case maybe of
      Just value -> value
      Nothing -> default

Le funzioni che accettano altre funzioni come parametri si chiamano funzioni di ordine superiore, ed anche queste possono essere generiche.

map : (a -> b) -> Maybe a -> Maybe b
map function maybe =
  case maybe of
    Just value ->
      Just (function value)

    Nothing ->
      Nothing

Istruzioni

In questo esercizio scriverai un TreasureChest generico (e anche magico!), per custodire un po' di tesoro.

1. Definisci il tipo personalizzato generico TreasureChest

Definisci un tipo personalizzato TreasureChest con una sola variante.

La variante deve avere un valore String associato, che servirà a memorizzare la password del forziere.

La variante deve avere anche un valore generico associato, che servirà a memorizzare il tesoro. Questo valore è generico, così il tesoro può essere qualsiasi cosa.

2. Definisci la funzione getTreasure

Questa funzione deve accettare due parametri

  • una String (per provare una password)
  • un tipo personalizzato generico TreasureChest

Questa funzione deve confrontare il tentativo di password fornito con la String contenuta nel TreasureChest.

La funzione deve restituire un Maybe.

Se le password corrispondono, restituisci Just con il valore generico contenuto nel TreasureChest (il tesoro!).

Se le password non corrispondono, restituisci Nothing.

3. Definisci la funzione multiplyTreasure

Questa funzione (di ordine superiore) deve accettare due parametri

  • una funzione moltiplicatrice che accetta un parametro generico e restituisce un array dello stesso tipo generico
  • un tipo personalizzato generico TreasureChest, anch'esso con lo stesso tipo generico

Questa funzione deve chiamare la funzione moltiplicatrice passandole il tesoro contenuto nel forziere.

La funzione deve restituire un nuovo TreasureChest, con la stessa password dell'originale e con il tesoro moltiplicato (il valore restituito).

Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Elm Exercism

Vuoi iniziare Il forziere del tesoro?

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