I can't seem to find a solution other than staying with a type-projection, only shorter:
trait Ex[A] { type L[S <: Sys[S]] = Expr[S, A] }
def name[S <: Sys[S]](p: Proc[S]): String =
p.attribute[Ex[String]#L]("name").fold("<unnamed>")(_.value)
This is still not what I want. Can I get rid of the type-projection altogether?
A second idea is to provide an extension method:
implicit class RichProc[S <: Sys[S]](val `this`: Proc[S]) extends AnyVal {
def attrExpr[A](key: String)
(implicit tag: ClassTag[Expr[S, A]]): Option[Expr[S, A]] =
`this`.attribute[({type Ex[~ <: Sys[~]] = Expr[~, A]})#Ex](key)
}
def name[S <: Sys[S]](p: Proc[S]): String =
p.attrExpr[String]("name").fold("<unnamed>")(_.value)