0Pricing
Scala for Backend Engineering & Functional Programming · درس

تعريف Instances

Instances ضمنية

تعريف Instances درس مجاني في Scala for Backend Engineering & Functional Programming على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Scala for Backend Engineering & Functional Programming، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Scala for Backend Engineering & Functional Programming 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

Defining Instances

An instance tells the compiler how a type class behaves for a specific type. In Scala, instances are usually marked implicit (Scala 2) or declared with given (Scala 3) so they are found automatically.

An implicit val Instance

For a simple type class, an implicit val is enough. The compiler finds it when a function needs a Show[Int].

trait Show[A] { def show(a: A): String }

object Main {
  implicit val intShow: Show[Int] = (a: Int) => s"Int=$a"

  def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

  def main(args: Array[String]): Unit = {
    println(display(123))
  }
}

implicitly: Summon an Instance

implicitly[Show[Int]] asks the compiler to fetch the in-scope instance. It is useful for testing that an instance exists or for accessing it directly.

trait Show[A] { def show(a: A): String }

object Main {
  implicit val intShow: Show[Int] = (a: Int) => s"<$a>"

  def main(args: Array[String]): Unit = {
    val s = implicitly[Show[Int]]
    println(s.show(8))
  }
}

Instances for Custom Types

Define an instance for your own case class. The data class stays clean; the formatting lives in the instance.

trait Show[A] { def show(a: A): String }

case class Point(x: Int, y: Int)

object Main {
  implicit val pointShow: Show[Point] = (p: Point) => s"(${p.x}, ${p.y})"

  def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

  def main(args: Array[String]): Unit = {
    println(display(Point(3, 4)))
  }
}

implicit def for Generic Instances

When an instance depends on another instance, use implicit def. Here a Show[List[A]] is built from a Show[A].

trait Show[A] { def show(a: A): String }

object Main {
  implicit val intShow: Show[Int] = (a: Int) => a.toString

  implicit def listShow[A](implicit s: Show[A]): Show[List[A]] =
    (xs: List[A]) => xs.map(s.show).mkString("[", ", ", "]")

  def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

  def main(args: Array[String]): Unit = {
    println(display(List(1, 2, 3)))
  }
}

Instances in the Companion Object

Placing instances in the type class's companion object means they are found automatically without any import. This is the recommended home for default instances.

trait Show[A] { def show(a: A): String }

object Show {
  implicit val intShow: Show[Int] = (a: Int) => s"i:$a"
  implicit val strShow: Show[String] = (a: String) => s"s:$a"
}

object Main {
  def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

  def main(args: Array[String]): Unit = {
    println(display(5))
    println(display("hi"))
  }
}

Implicit Scope and Priority

The compiler searches several places for an instance: the local/imported scope first, then the companion objects of the types involved. If two instances are equally specific, you get an ambiguous implicit error.

Context Bound Shorthand

The syntax def f[A: Show](a: A) is a context bound: it means there must be an implicit Show[A] in scope. Inside, retrieve it with implicitly.

trait Show[A] { def show(a: A): String }

object Main {
  implicit val intShow: Show[Int] = (a: Int) => s"n=$a"

  def display[A: Show](a: A): String = implicitly[Show[A]].show(a)

  def main(args: Array[String]): Unit = {
    println(display(77))
  }
}

A Summoner Helper

Libraries add an apply method to the companion as a convenient summoner: Show[Int] returns the instance. It is cleaner than implicitly.

trait Show[A] { def show(a: A): String }

object Show {
  def apply[A](implicit s: Show[A]): Show[A] = s
  implicit val intShow: Show[Int] = (a: Int) => s"=$a"
}

object Main {
  def main(args: Array[String]): Unit = {
    println(Show[Int].show(10))
  }
}

Avoiding Orphan Instances

An orphan instance is one defined neither with the type class nor with the type. They are legal but can cause inconsistent behavior across imports. Prefer companion-object instances to keep them coherent.

Putting It Together

A complete program: companion-object instances, a derived list instance, and a summoner.

trait Show[A] { def show(a: A): String }

object Show {
  def apply[A](implicit s: Show[A]): Show[A] = s
  implicit val intShow: Show[Int] = _.toString
  implicit def listShow[A](implicit s: Show[A]): Show[List[A]] =
    (xs: List[A]) => xs.map(s.show).mkString(", ")
}

object Main {
  def main(args: Array[String]): Unit = {
    println(Show[List[Int]].show(List(4, 5, 6)))
  }
}

Quick Check

Test your knowledge of defining instances.

Recap

You learned to define instances:

  • implicit val for simple instances, implicit def for derived ones.
  • Summon with implicitly or a companion apply.
  • Use context bounds [A: Show] as shorthand.
  • Put instances in companion objects to avoid orphans.

الأسئلة الشائعة

هل درس «تعريف Instances» مجاني؟

نعم — نص درس «تعريف Instances» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Scala for Backend Engineering & Functional Programming، انتقل إلى CoddyKit PRO. تتضمن دورة Scala for Backend Engineering & Functional Programming 4 دروس في المجموع.

ماذا ستتعلم في «تعريف Instances»؟

Instances ضمنية تتمرن على Scala for Backend Engineering & Functional Programming مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Scala for Backend Engineering & Functional Programming؟

لا تُشترط خبرة سابقة. Scala for Backend Engineering & Functional Programming على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «تعريف Instances»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Scala for Backend Engineering & Functional Programming هذا؟

نعم. كل درس في Scala for Backend Engineering & Functional Programming يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. نمط Type Class
  2. تعريف Instances
  3. Type Classes الشائعة
  4. اشتقاق Type Class
← العودة إلى Scala for Backend Engineering & Functional Programming