Percursos
/
Elm
Elm
/
Exercícios
/
Baú do Tesouro
Baú do Tesouro

Baú do Tesouro

Exercício de aprendizagem

Introdução

Genéricos

Introdução

Os genéricos são uma funcionalidade da linguagem que permite reutilizar código. Por exemplo, não deveria importar que tipo de valores uma lista contém para calcular o seu comprimento. É por isso que a função length usa um parâmetro de tipo genérico a na sua assinatura de tipo.

length : List a -> Int

Parâmetros em tipos

Quando um tipo é genérico em relação a outro tipo, usamos um nome em minúsculas para esse outro tipo e chamamos-lhe um parâmetro de tipo. Exemplos comuns são os tipos personalizados 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

Uma observação importante sobre os nomes dos parâmetros de tipo é que podem ter vários carateres. A única restrição é que têm de ser nomes em minúsculas. Por isso, quando é útil, tendemos a dar-lhes nomes descritivos.

Um tipo pode ser genérico em relação a vários outros tipos e, por isso, ter vários parâmetros de tipo. Nesse caso, cada tipo independente recebe um nome diferente em minúsculas. O facto de serem independentes não impede que se tornem o mesmo tipo, apenas permite que sejam diferentes.

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

Os aliases de tipo de registo também podem ter parâmetros de tipo, embora seja menos comum.

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

Parâmetros de tipo em funções

Como os tipos podem ser genéricos, as funções também podem. É possível escrever funções que lidam com tipos genéricos, como a Maybe.withDefault.

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

As funções que recebem outras funções como parâmetros chamam-se funções de ordem superior, e estas também podem ser genéricas.

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

    Nothing ->
      Nothing

Instruções

Neste exercício vais escrever um TreasureChest genérico (e mágico!) para guardar algum tesouro.

1. Define o tipo personalizado genérico TreasureChest

Define um tipo personalizado TreasureChest com uma única variante.

A variante deve ter um valor String associado, que será usado para guardar a palavra-passe do baú do tesouro.

A variante deve também ter um valor genérico associado, que será usado para guardar o tesouro. Este valor é genérico para que o tesouro possa ser qualquer coisa.

2. Define a função getTreasure

Esta função deve receber dois parâmetros

  • uma String (para tentar uma palavra-passe)
  • um tipo personalizado genérico TreasureChest

Esta função deve comparar a tentativa de palavra-passe fornecida com a String no TreasureChest.

A função deve devolver um Maybe.

Se as palavras-passe coincidirem, devolve Just com o valor genérico do TreasureChest (o tesouro!)

Se as palavras-passe não coincidirem, devolve Nothing.

3. Define a função multiplyTreasure

Esta função (de ordem superior) deve receber dois parâmetros

  • uma função multiplicadora que recebe um parâmetro genérico e devolve uma lista do mesmo tipo genérico
  • um tipo personalizado genérico TreasureChest, também com o mesmo tipo genérico

Esta função deve chamar a função multiplicadora com o tesouro que está no baú.

A função deve devolver um novo TreasureChest, com a mesma palavra-passe do original e com o tesouro multiplicado (o valor devolvido)

Editar via GitHub A ligação abre numa nova janela ou separador
Elm Exercism

Estás pronto para começar Baú do Tesouro?

Inscreve-te no Exercism para aprenderes e dominares Elm com 28 conceitos110 exercícios, e mentoria humana real, tudo grátis.