2
\$\begingroup\$

I have a type representing an immutable order which contains immutable order lines that belong to it. I want to use path-dependent types for this. Obviously you cannot instantiate a path-dependent type without having the value it depends on, so I decided to take a function from the constructor. Since (order: Order) => Seq[order.OrderLine] is impossible, I use a simple structural type.

final class Order private() {
  case class OrderLine(x: Int, y: Double) { }

  def this(makeOrderLines: { def apply(order: Order): Seq[order.OrderLine] }) = {
    this()
    _orderLines = makeOrderLines(this)
  }

  private var _orderLines: Seq[OrderLine] = null
  def orderLines = _orderLines
}

object Main extends App {
  val order = new Order(new {
    def apply(order: Order) =
      Seq(order.OrderLine(1, 1.0), order.OrderLine(2, 2.0))
  })
  println(order.orderLines)
}

I find this approach very ugly. Especially not being able to use a lambda expression irks me (the lambda expression would return Seq[Order#OrderLine] instead of Seq[order.OrderLine] since it has be of type Function1[_, _] where path-dependent types are not possible).

Is there a better way of doing this?

\$\endgroup\$
  • 1
    \$\begingroup\$ I'm not sure why you absolutely want to use path-dependent types. Wouldn't defining OrderLine in a companion object Order be clean enough? It would be a more common approach. \$\endgroup\$ – toto2 Jul 25 '14 at 1:57
1
\$\begingroup\$

Taking a shower can do wonders. :)

You can take tuples instead and convert those to this.OrderLines in the constructor.

final class Order private() {
  case class OrderLine(x: Int, y: Double) { }

  def this(rawOrderLines: Seq[(Int, Double)]) = {
    this()
    _orderLines = rawOrderLines.map { case (x, y) => OrderLine(x, y) }
  }

  private var _orderLines: Seq[OrderLine] = null
  def orderLines = _orderLines
}

object Main extends App {
  val order = new Order(Seq((1, 1.0), (2, 2.0)))
  println(order.orderLines)
}

It’s simpler and more concise, although the call-site may still be rather confusing (not that it wasn’t already).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.