0Pricing
Scala for Backend Engineering & Functional Programming · Aula

Tipos de dados algébricos

Modele seu domínio.

Tipos de dados algébricos é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.

O que é um ADT?

Um tipo de dados algébrico (ADT) é um tipo criado pela combinação de outros tipos. Em Scala, você modela ADTs com um sealed trait e variantes de case class e case object.

Os ADTs permitem descrever com precisão a forma dos dados do seu domínio.

Tipos soma

Um tipo soma significa que um valor é uma de várias alternativas (um OR). Um semáforo é Vermelho OR Amarelo OR Verde.

Você expressa isso com um trait selado e várias variantes.

sealed trait Light
case object Red extends Light
case object Yellow extends Light
case object Green extends Light
object Main {
  def main(args: Array[String]): Unit = {
    val l: Light = Yellow
    println(l)
  }
}

Tipos produto

Um tipo produto significa que um valor combina vários campos (um AND). Um ponto tem um x AND um y.

As classes de caso são tipos produto.

case class Point(x: Int, y: Int)
object Main {
  def main(args: Array[String]): Unit = {
    val p = Point(3, 4)
    println(s"${p.x} and ${p.y}")
  }
}

Combinando tipos soma e produto

Os ADTs reais combinam ambos: um trait selado (soma) cujas variantes são classes de caso (produtos).

Aqui, uma Shape é um Circle (com raio) OR um Rectangle (com largura e altura).

sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(w: Double, h: Double) extends Shape
object Main {
  def main(args: Array[String]): Unit = {
    val s: Shape = Rectangle(3, 4)
    println(s)
  }
}

Operando em um ADT

Você processa um ADT usando correspondência de padrões em suas variantes. Cada ramo trata de uma forma.

sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(w: Double, h: Double) extends Shape
object Main {
  def area(s: Shape): Double = s match {
    case Circle(r)       => 3.14159 * r * r
    case Rectangle(w, h) => w * h
  }
  def main(args: Array[String]): Unit = {
    println(area(Circle(2)))
    println(area(Rectangle(3, 4)))
  }
}

Modelando um domínio

Os ADTs tornam os estados inválidos impossíveis de representar. Modele um método de pagamento como um conjunto fechado de opções válidas.

sealed trait PaymentMethod
case class CreditCard(number: String) extends PaymentMethod
case class BankTransfer(iban: String) extends PaymentMethod
case object Cash extends PaymentMethod
object Main {
  def main(args: Array[String]): Unit = {
    val m: PaymentMethod = Cash
    println(m)
  }
}

ADTs recursivos

Um ADT pode referir-se a si próprio, permitindo modelar árvores e listas. Aqui está uma árvore binária simples.

sealed trait Tree
case object Leaf extends Tree
case class Node(value: Int, left: Tree, right: Tree) extends Tree
object Main {
  def main(args: Array[String]): Unit = {
    val t: Tree = Node(1, Leaf, Node(2, Leaf, Leaf))
    println(t)
  }
}

Percorrendo um ADT recursivo

A recursão combinada à correspondência permite processar toda a estrutura. Aqui, somamos cada valor de uma árvore.

sealed trait Tree
case object Leaf extends Tree
case class Node(value: Int, left: Tree, right: Tree) extends Tree
object Main {
  def sum(t: Tree): Int = t match {
    case Leaf            => 0
    case Node(v, l, r)   => v + sum(l) + sum(r)
  }
  def main(args: Array[String]): Unit = {
    val t = Node(1, Node(2, Leaf, Leaf), Node(3, Leaf, Leaf))
    println(sum(t))
  }
}

Por que usar ADTs?

Os ADTs são poderosos porque:

  • Descrevem os dados com precisão como somas e produtos
  • Tornam impossível construir estados ilegais
  • Combinam perfeitamente com a correspondência exaustiva de padrões
  • Podem ser ampliados para estruturas recursivas, como árvores e listas

ADTs versus herança

A POO tradicional espalharia o comportamento pelas subclasses. Os ADTs mantêm as definições de dados fechadas e colocam o comportamento em funções que usam correspondência de padrões.

Essa separação entre dados e comportamento é uma característica marcante do design funcional.

Reunindo tudo

Um pequeno ADT completo com uma função que trata de todas as variantes.

sealed trait Json
case class JNum(n: Double) extends Json
case class JStr(s: String) extends Json
case object JNull extends Json
object Main {
  def render(j: Json): String = j match {
    case JNum(n) => n.toString
    case JStr(s) => "\"" + s + "\""
    case JNull   => "null"
  }
  def main(args: Array[String]): Unit = {
    List(JNum(3.0), JStr("hi"), JNull).foreach(j => println(render(j)))
  }
}

Verificação rápida

Teste sua compreensão sobre ADTs.

Recapitulação

Você aprendeu a criar tipos de dados algébricos:

  • Tipos soma: trait selado com várias variantes (OR)
  • Tipos produto: classes de caso com campos (AND)
  • Combine-os para modelar domínios com precisão
  • Os ADTs podem ser recursivos (árvores e listas)
  • Processe-os com correspondência de padrões

Perguntas Frequentes

A aula “Tipos de dados algébricos” é grátis?

Sim — o texto completo de “Tipos de dados algébricos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.

O que vou aprender em “Tipos de dados algébricos”?

Modele seu domínio. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?

Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Tipos de dados algébricos”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?

Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Classes case
  2. Traits seladas
  3. Tipos de dados algébricos
  4. Correspondência exaustiva
← Voltar para Scala for Backend Engineering & Functional Programming