एक पूरा काम कर उदाहरण के लिए, मान लीजिए हम कुछ सरल अल्जेब्रास मिल गया है:
sealed trait AuthOp[A]
case class Login(user: String, pass: String) extends AuthOp[Option[String]]
case class HasPermission(user: String, access: String) extends AuthOp[Boolean]
sealed trait InteractOp[A]
case class Ask(prompt: String) extends InteractOp[String]
case class Tell(msg: String) extends InteractOp[Unit]
sealed trait LogOp[A]
case class Record(msg: String) extends LogOp[Unit]
और कुछ (व्यर्थ लेकिन संकलन करने योग्य) दुभाषिए:
import scalaz.~>, scalaz.Id.Id
val AuthInterpreter: AuthOp ~> Id = new (AuthOp ~> Id) {
def apply[A](op: AuthOp[A]): A = op match {
case Login("foo", "bar") => Some("foo")
case Login(_, _) => None
case HasPermission("foo", "any") => true
case HasPermission(_, _) => false
}
}
val InteractInterpreter: InteractOp ~> Id = new (InteractOp ~> Id) {
def apply[A](op: InteractOp[A]): A = op match {
case Ask(p) => p
case Tell(_) =>()
}
}
val LogInterpreter: LogOp ~> Id = new (LogOp ~> Id) {
def apply[A](op: LogOp[A]): A = op match {
case Record(_) =>()
}
}
इस बिंदु पर आप इस तरह के दुभाषियों के HList
पर गुना करने में सक्षम होना चाहिए:
import scalaz.Coproduct
import shapeless.Poly2
object combine extends Poly2 {
implicit def or[F[_], G[_], H[_]]: Case.Aux[
F ~> H,
G ~> H,
({ type L[x] = Coproduct[F, G, x] })#L ~> H
] = at((f, g) =>
new (({ type L[x] = Coproduct[F, G, x] })#L ~> H) {
def apply[A](fa: Coproduct[F, G, A]): H[A] = fa.run.fold(f, g)
}
)
}
लेकिन यह उन कारणों से काम नहीं करता है जो टाइप अनुमान के साथ कुछ करने के लिए प्रतीत होते हैं। यह एक कस्टम प्रकार वर्ग लिखने के लिए भी मुश्किल नहीं है, हालांकि:
import scalaz.Coproduct
import shapeless.{ DepFn1, HList, HNil, :: }
trait Interpreters[L <: HList] extends DepFn1[L]
object Interpreters {
type Aux[L <: HList, Out0] = Interpreters[L] { type Out = Out0 }
implicit def interpreters0[F[_], H[_]]: Aux[(F ~> H) :: HNil, F ~> H] =
new Interpreters[(F ~> H) :: HNil] {
type Out = F ~> H
def apply(in: (F ~> H) :: HNil): F ~> H = in.head
}
implicit def interpreters1[F[_], G[_], H[_], T <: HList](implicit
ti: Aux[T, G ~> H]
): Aux[(F ~> H) :: T, ({ type L[x] = Coproduct[F, G, x] })#L ~> H] =
new Interpreters[(F ~> H) :: T] {
type Out = ({ type L[x] = Coproduct[F, G, x] })#L ~> H
def apply(
in: (F ~> H) :: T
): ({ type L[x] = Coproduct[F, G, x] })#L ~> H =
new (({ type L[x] = Coproduct[F, G, x] })#L ~> H) {
def apply[A](fa: Coproduct[F, G, A]): H[A] =
fa.run.fold(in.head, ti(in.tail))
}
}
}
और फिर आप अपने combine
लिख सकते हैं:
def combine[L <: HList](l: L)(implicit is: Interpreters[L]): is.Out = is(l)
और इसका इस्तेमाल करते हैं:
type Language0[A] = Coproduct[InteractOp, AuthOp, A]
type Language[A] = Coproduct[LogOp, Language0, A]
val interpreter: Language ~> Id =
combine(LogInterpreter :: InteractInterpreter :: AuthInterpreter :: HNil)
आप सक्षम हो सकता है Poly2
संस्करण काम करने के लिए, लेकिन इस प्रकार की कक्षा शायद मेरे लिए पर्याप्त सरल होगी। दुर्भाग्य से आप जिस तरह से चाहते हैं, Language
टाइप उपनाम की परिभाषा को सरल बनाने में सक्षम नहीं होंगे।
आप पॉलिमॉर्फिक फ़ंक्शन का उपयोग करके 'एचएलआईस्ट' को फोल्ड कर सकते हैं। कृपया, [आकारहीन गाइड] (https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#heterogenous-lists) देखें। –