Search code examples
scalagenericstypestype-annotation

Find a decent alternative to forced explicit type annotation?


While testing some code that I recently created i figured that some passages are not compiling without explicit type annotation. I tried to minimize the problem in the following code snippet:

case class Base[E,S](al:Set[E],sts:Set[MidState[S]],ss:MidState[S],
                            d:Map[(MidState[S],E),MidState[S]],aS:Set[MidState[S]])

case class Edge[E,S](state_1: MidState[S],l:E ,state_2: MidState[S])

sealed trait MidState[S] extends BaseState[S]

sealed case class State[S](l:S)
  extends MidState[S]

case object FailureState extends MidState[Nothing]

Base has a companion object with an apply method defined as follows:

object Base {
  def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
  aS:Set[MidState[S]],partialMode:Boolean): Base[E,S]

When i am trying to instantiate Base with this apply method i cannot get around an explicit type annotation for aS:

val aS : Set[MidState[String]] = (State("C") :: Nil).toSet
val base = Base(edges,State("A"),aS,partialMode = true)

If i erase the explicit type annotation for aS, aS is of type Set[State[S]] and not Set[MidState[S]] which it needs to be for the apply method. Is there any better solution to avoid this explicit type annotation despite inserting (State("C") :: Nil).toSet directly into the apply method?


Solution

  • The first thing you could do is to remove all the :: Nil and .toSet and : ... noise:

    val aS = Set[MidState[String]](State("C"))
    

    This is actually quite common: for example, it frequently occurs as the first argument in folds, where one has to explicitly write Set[Int]() or Set.empty[Int] in order to get the types right.

    If this is still too noisy, just add appropriate factory methods to MidState:

    object MidState {
      def apply[S](s: S): MidState[S] = State(s)
    }
    

    and then invoke the factory method that constructs the right type of object right away:

    val bS = Set(MidState("C"))