Maths noob
Maths noob

Reputation: 1802

Scala: type inference issue

I have:

sealed trait Par[A]{def foo = ???}
case class Unit[A](v: () => A) extends Par[A]
case class Map2[L, R, A](parLeft: Par[L],
                         parRight: Par[R],
                         map: (L, R) => A) extends Par[A]

my problem is that when I pattern match on p:Par[A] to do something like this:

def getSequentially: A = this match {
  case Par.Unit(f) => f()
  case Par.Map2(a, b, f) => f(a.getSequentially, b.getSequentially)
}    

L and R are inferred to be Any in Intellij's type inspector and getSequentially calls are highlighted in red, warning: type mismatch, expected Nothing, actual Any, since f is expected to be of type: (Nothing, Nothing) => A. Although it actually runs and compiles.

I think I understand what the problem is and I should be able to solve it with existential types in the definition of Map2. Only problem is that the map parameter has a dependent type, so I don't know how to do that. Maybe I should do a variation of the AUX pattern?

My question is, firstly why it compiles and secondly, if there is a way of restructuring the type dependency so that it no longer issues a warning.

Upvotes: 1

Views: 107

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51723

If you want to have existentials you can use typed patterns:

sealed trait Par[A]{
  def getSequentially: A = this match {
    case x: Par.Unit[A] => x.v()
    case x: Par.Map2[_, _, A] => x.map(x.parLeft.getSequentially, x.parRight.getSequentially)
  }
}

object Par {
  case class Unit[A](v: () => A) extends Par[A]
  case class Map2[L, R, A](parLeft: Par[L],
                           parRight: Par[R],
                           map: (L, R) => A) extends Par[A]
}

IntelliJ seems not to highlight this.

Upvotes: 2

Related Questions