Discord is now Scala’s main chat platform. Please join us at https://discord.com/invite/scala
I’m having some problems with path dependent types. Not sure if what I am trying to do makes sense. Anyway here is an example:
sealed trait Foo {
type F
}
object Bar extends Foo {
type F = Array[Byte]
}
trait Baz[B] {
def b(b: B): String
}
object Baz {
implicit val bazByteArray: Baz[Array[Byte]] = (b: Array[Byte]) => new String(b)
}
def f(a: Foo): Baz[a.F] = {
val baz = a match {
case bar@Bar => g(bar)
}
baz
} // Expression of type Baz[(a.type with Bar.type)#F] doesn't conform to Baz[a.F]
def g(a: Foo)(implicit baz: Baz[a.F]): Baz[a.F] = {
baz
}
val x1: Bar.type = Bar
val y1: Baz[x1.F] = f(x1)
val x2: Foo = Bar
val y2: Baz[x2.F] = f(x2) // Expression of type Baz[Foo#F] doesn't conform to expected type Baz[x2.F]
What I don’t get is why g
compiles but f
doesn’t. Are the types not the same?
trait Expr { def eval: Either[String, Double] }
sealed trait BinOp extends Expr {
def a: Expr
def b: Expr
def op: (Double, Double) => Either[String, Double]
protected def safe(f: (Double, Double) => Double): (Double, Double) => Either[String, Double] =
(xa, xb) => Right(f(xa, xb))
def eval = a match {
case Left(s) => Left(s)
case Right(xa) => b match {
case Left(s) => Left(s)
case Right(xb) => op(xa, xb)
}
}
final case class Add(a: Expr, b: Expr) extends BinOp { val op = safe(_ + _) }
final case class Sub(a: Expr, b: Expr) extends BinOp { val op = safe(_ - _) }
final case class Mul(a: Expr, b: Expr) extends BinOp { val op = safe(_ * _) }
final case class Div(a: Expr, b: Expr) extends BinOp {
val op = (xa, xb) => if (xb == 0) Left("Division by 0") else Right(xa / xb)
}
Left
and Right