型クラスの導出
インスタンスを自動生成します。
「型クラスの導出」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
導出とは
型クラスの導出は、型の構造からインスタンスを自動生成します。そのため、case classごとに定型コードを手作業で記述する必要がありません。コンパイラーがフィールドからインスタンスを構築します。
定型コードの問題
導出がなければ、新しいcase classごとに手動でインスタンスが必要です。20個のcase classに対してShowを用意する場合、ほぼ同一の定義を20個書くことになります。導出により、この繰り返しをなくせます。
まずは手動で合成する
自動導出の前に、フィールドのインスタンスから手動でインスタンスを合成できることを確認しましょう。これが、導出によって自動化される原理です。
trait Show[A] { def show(a: A): String }
case class User(name: String, age: Int)
object Main {
implicit val strShow: Show[String] = s => s
implicit val intShow: Show[Int] = _.toString
implicit val userShow: Show[User] = (u: User) =>
s"User(${strShow.show(u.name)}, ${intShow.show(u.age)})"
def main(args: Array[String]): Unit = {
println(userShow.show(User("Ann", 30)))
}
}帰納的なインスタンス
導出は帰納的に機能します。まずプリミティブ型のインスタンスを定義し、次にそれらを組み合わせて積(case class)や和(sealed trait)のインスタンスを作ります。導出されたインスタンスは、その構成要素から構築されます。
Scala 3のderivesキーワード
Scala 3はderives句をサポートしています。derivedメソッドを持つ型クラスは、1つのキーワードで型に適用できます。(概念的なスニペットです。導出可能な型クラスが必要です。)
enum Color derives CanEqual:
case Red, Green, Blue
@main def run(): Unit =
println(Color.Red == Color.Red)Mirrorベースの導出
Scala 3の導出では、コンパイル時に型の構造(フィールドの型と名前)を公開するscala.deriving.Mirrorを使用します。derivedメソッドは、mirrorの要素インスタンスを順に畳み込み、全体を構築します。
半自動導出
Catsなどのライブラリは半自動導出を提供します。deriveShowのような1行の記述で型ごとに導出を有効にできるため、コンパイル時間を予測しやすくしながら定型コードを削減できます。
自動導出と半自動導出
2つの方式があります。
- 自動:暗黙インポートによって、必要な場所でインスタンスが自動的に用意されます。便利ですが、コンパイルが遅くなることがあります。
- 半自動:型ごとに明示的なderive呼び出しを1つ記述します。より細かく制御でき、ビルドも高速です。
sealed traitの導出
sealed hierarchy(sum type)では、導出されたインスタンスが、値がどのサブタイプに属するかに応じて処理を振り分けます。ここでは、導出によって自動化される仕組みを手動で示します。
trait Show[A] { def show(a: A): String }
sealed trait Shape
case class Circle(r: Int) extends Shape
case class Square(s: Int) extends Shape
object Main {
implicit val shapeShow: Show[Shape] = {
case Circle(r) => s"Circle($r)"
case Square(s) => s"Square($s)"
}
def main(args: Array[String]): Unit = {
println(shapeShow.show(Circle(5)))
println(shapeShow.show(Square(3)))
}
}導出を使用する場面
次のような場合は導出を使用します。
- 同じtype classを必要とするデータ型(JSON codec、Show、Eq)が多数ある場合。
- インスタンスを構造から機械的に生成できる場合。
動作が独自仕様である場合や、パフォーマンスが重要な場合は、インスタンスを手動で記述します。
汎用的な等価性の例
等価性は、導出可能なtype classの代表例です。case classに対する標準の==も、コンパイラーが生成する構造的等価性の一種です。
case class Coord(x: Int, y: Int)
object Main {
def main(args: Array[String]): Unit = {
println(Coord(1, 2) == Coord(1, 2))
println(Coord(1, 2) == Coord(3, 4))
}
}理解度チェック
導出についての理解度を確認しましょう。
まとめ
type classの導出について学びました。
- インスタンスは、フィールドやcaseのインスタンスから帰納的に構築されます。
- Scala 3では
Mirrorとderivesキーワードを使用します。 - 利便性を重視するなら自動、制御性を重視するなら半自動を選びます。
- 多くのデータ型にまたがる定型コードの削減に利用できます。
よくある質問
「型クラスの導出」レッスンは無料ですか?
はい。「型クラスの導出」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと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は初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「型クラスの導出」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?
はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。