-
Notifications
You must be signed in to change notification settings - Fork 534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Witness should provide the evidence of value.type =:= T
#753
Comments
Or we can define trait Witness {
type T = value.type
val value: Any
}
object Witness {
type Lt[+T0] = Witness {
val value: T0
}
type Aux[T0] = Witness.Lt[T0] {
type T = T0
}
} Then the evidence can be created as following: def ev(w: Witness): w.value.type =:= w.T = {
implicitly
} |
@Atry have you tried that alternative definition of |
As an aside, a more idiomatic approach to the motivating problem would be something along the lines of, trait Document {
trait Element
def createElement(): Element
def appendChild(element: Element): Unit
} ie. use path dependent types to encode family polymorphism. |
@milessabin At least the approach works for Dotty 😄 https://scastie.scala-lang.org/Atry/H5ltvYE9T9iD8IwRSdDESg/5 trait Witness {
type T = value.type
val value: Any
}
object Witness {
type Aux[T0] = Witness {
type T = T0
val value: T0
}
}
trait Element[+Owner]
trait Document {
def createElement(): Element[this.type]
def appendChild(element: Element[this.type]): Unit
}
def proveSameOwner(w: Witness) = {
implicitly[Element[w.T] =:= Element[w.value.type]]
}
def appendToDocument[Owner <: Document with Singleton](
element: Element[Owner])(
implicit w: Witness.Aux[Owner]) = {
val ev: Element[w.T] =:= Element[w.value.type] = proveSameOwner(w)
w.value.appendChild(ev(element))
} |
Could you try modifying the shapeless definition as you suggest and see what (if anything) breaks? |
The new https://scalafiddle.io/sf/c6YMHlX/0 trait Witness {
type T = value.type
val value: AnyRef
}
object Witness {
type Aux[T0] = Witness {
type T = T0
val value: T0
}
}
trait Element[+Owner]
trait Document {
def createElement(): Element[this.type]
def appendChild(element: Element[this.type]): Unit
}
trait Prover {
val w: {
type T
val value: AnyRef
}
def proveSameOwner: Element[w.T] =:= Element[w.value.type]
}
trait WitnessProver extends Prover {
val w: Witness
def proveSameOwner = implicitly[Element[w.T] =:= Element[w.value.type]]
}
def appendToDocument[Owner <: Document with Singleton](
element: Element[Owner])(
implicit w0: Witness.Aux[Owner]) = {
val prover: Prover { val w: Witness.Aux[Owner] } = new WitnessProver { val w = w0 }
import prover._
w.value.appendChild(prover.proveSameOwner(element))
} |
The current |
Suppose we are creating a XML processing library, we want to ensure all the methods in a XML document only applies to elements that belong to the document.
We can define the document type like this:
However, this approach is problematic when we summon the document for an element:
The problem is that Scala compiler does not know
Element[witnessOwner.value.type]
andElement[Owner]
are the same type.This problem can be resolved if we add a
value.type =:= T
evidence inWitness
, along with the ability of substitution in Scala 2.13.The text was updated successfully, but these errors were encountered: