3

Two implicits are needed in the function, but I can't have them in the same parameter list, because I get dependent method type. So I considered currying once more, but that gives me a syntax error. What's the correct way to do this?

def add[A](newAnnotations: Seq[A])
    (implicit maybeAdd: MaybeAdd[L, Seq[A]])
    (implicit mod: Modifier[maybeAdd.Out, Seq[A], Seq[A]]):
    Slab[Content, maybeAdd.Out] = {
  val l = maybeAdd(annotations, Seq[A]())
  l.updateWith(_ ++ newAnnotations)
}
Chris Martin
  • 30,334
  • 10
  • 78
  • 137
Reactormonk
  • 21,472
  • 14
  • 74
  • 123

2 Answers2

1

I edited MaybeAdd to have an Aux type, as suggested by @milessabin.

def add[A, Out0](newAnnotations: Seq[A])(implicit maybeAdd: MaybeAdd.Aux[L, Seq[A], Out0], mod: Modifier[Out0, Seq[A], Seq[A]]): Slab[Content, mod.Out] = {
  val l = maybeAdd(annotations, Seq[A]())
  new Slab(content, mod(l, _ ++ newAnnotations))
}
Reactormonk
  • 21,472
  • 14
  • 74
  • 123
0

Note: the syntax error is likely to be:

illegal dependent method type: 
parameter appears in the type of another parameter in the same section or an earlier one 

Meaning one cannot use the dependent type in the same section, only in the next parameters block or as a return type only.

See "A short introduction to the Aux pattern" byLuigi.

 type Aux[A0, B0] = Foo[A0] { type B = B0  }

basically Aux is just a way to extract the result of a type level computation

As noted in "Why is the Aux technique required for type-level computations?"

the Aux type aliases are entirely a syntactic convenience.

The Aux version has a couple of advantages over writing out the type refinements in this way: it's less noisy, and it doesn't require us to remember the name of the type member.
These are purely ergonomic issues, though—the Aux aliases make our code a little easier to read and write, but they don't change what we can or can't do with the code in any meaningful way.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250