Search code examples
scalasequences

Typecheck when mapping some items in a sequence to None


The following code traverses some list of nodes and creates Paragraph or Heading objects for some of the nodes:

  abstract class Element    
  case class Paragraph(node: Node) extends Element
  case class Heading(mainNode: Node, textNode: Node) extends Element

  val elements =
      parent.child.map(n =>
        if (n.label == "p") Paragraph(n)
        else if (n.label.matches("h\d")) Heading(n, n.child.head)
        else None)

Next, I would like to get rid of the None elements and pass elements to some function that requires Seq[Element]. However, the type of elements is Seq[Product with Serializable] rather than Seq[Element]. Why, and how can I make the type stronger?


Solution

  • Use collect instead of map to keep only the elements you want:

    val elements = parent.child.collect {
        case n if (n.label == "p") => Paragraph(n)
        case n if (n.label.matches("h\d")) => Heading(n, n.child.head))
    }
    

    Anything that isn't defined within the PartialFunction you pass to collect is discarded.

    There's no reason to map to None if you're just going to discard the elements anyway. And if you do for some reason want to keep the None instances, then the others should be mapped to Some[Element] so that you'd have Seq[Option[Element].