インスタンスの定義
暗黙のインスタンスです。
「インスタンスの定義」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
インスタンスの定義
インスタンスは、特定の型に対して型クラスがどのように振る舞うかをコンパイラーに伝えます。Scalaでは通常、インスタンスにimplicit(Scala 2)を付けるか、given(Scala 3)で宣言し、自動的に見つけられるようにします。
implicit valインスタンス
単純な型クラスなら、implicit valだけで十分です。関数が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:インスタンスを召喚する
implicitly[Show[Int]]は、スコープ内にあるインスタンスをコンパイラーに取得させます。インスタンスの存在をテストしたり、直接アクセスしたりする場合に便利です。
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))
}
}カスタム型のインスタンス
独自のcase classに対するインスタンスを定義します。データクラスはきれいなまま保ち、フォーマット処理はインスタンスに置きます。
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
あるインスタンスが別のインスタンスに依存する場合は、implicit defを使用します。ここではShow[A]からShow[List[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)))
}
}コンパニオンオブジェクト内のインスタンス
型クラスのコンパニオンオブジェクトにインスタンスを置くと、importなしで自動的に見つけられます。デフォルトインスタンスの配置場所として推奨されます。
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"))
}
}暗黙スコープと優先順位
コンパイラーはいくつかの場所からインスタンスを検索します。まずローカルスコープとimportされたスコープを検索し、次に関係する型のコンパニオンオブジェクトを検索します。同じ具体性のインスタンスが2つあると、ambiguous implicitエラーになります。
コンテキスト境界の省略記法
def f[A: Show](a: A)という構文はcontext boundです。これは、スコープ内に暗黙のShow[A]が存在しなければならないことを意味します。内部では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))
}
}召喚ヘルパー
ライブラリでは、便利なsummonerとしてコンパニオンにapplyメソッドを追加します。Show[Int]でインスタンスを返せます。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))
}
}孤児インスタンスを避ける
孤児インスタンスとは、型クラスとも型とも一緒に定義されていないインスタンスです。合法ではありますが、importによって動作が一貫しなくなる可能性があります。一貫性を保つため、コンパニオンオブジェクトのインスタンスを優先してください。
まとめて確認する
コンパニオンオブジェクトのインスタンス、派生したリストインスタンス、召喚ヘルパーを含む完全なプログラムです。
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)))
}
}理解度チェック
インスタンスの定義に関する知識を確認しましょう。
まとめ
インスタンスの定義について学びました。
- 単純なインスタンスには
implicit val、派生インスタンスにはimplicit defを使用します。 implicitlyまたはコンパニオンのapplyで召喚します。[A: Show]のようなcontext boundを省略記法として使用します。- 孤児インスタンスを避けるため、インスタンスはコンパニオンオブジェクトに置きます。
AI チューターと学ぶ Scala — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 39
- レッスン
- 143
よくある質問
「インスタンスの定義」レッスンは無料ですか?
はい。「インスタンスの定義」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Scala for Backend Engineering & Functional Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
「インスタンスの定義」で何を学びますか?
暗黙のインスタンスです。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Scala for Backend Engineering & Functional Programmingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのScala for Backend Engineering & Functional Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「インスタンスの定義」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?
はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。