LoginSignup
3
3

More than 5 years have passed since last update.

型クラスの練習:プロパー型と型コンストラクタとの組み合わせ

Last updated at Posted at 2014-11-14

型クラス(Type Class)の練習

プロパー型

まずはプロパー型(proper type)と呼ばれる普通のヤツ。ここではIntとStringに対応した例。
implicitの宣言として、valでもobjectでもいけるので2つ書いておいた。

object Main extends App {

  def decorate[T](x: T)(implicit deco: Decorating[T]) = deco(x)

  trait Decorating[T] {
    def apply(x: T): String
  }

  implicit val DecoratingString = new Decorating[String] {
    def apply(x: String) = s"SSS $x SSS"
  }

  implicit object DecoratingInt extends Decorating[Int] {
    def apply(x: Int) = s"III $x III"
  }

  println(decorate(100))  // III 100 III
  println(decorate("hello")) // SSS hello SSS
}

型コンストラクタ

次に1階カインド型(1st-order-kinded type)とか型コンストラクタ(type constructor)とか呼ばれる型パラメータを取るヤツ。
ここではOptionを使う。

以下、Option[String]に対応した例。
Option[Int]も同じようにやるだけなので省略。

implicit object OptionString extends Decorating[Option[String]] {
  def apply(x: Option[String]) = x.fold("")("OOO SSS " + (_:String) + " SSS OOO")
}

println(decorate(Option("hello")))  // OOO SSS hello SSS OOO

組み合わせ

上記でも出来るのだが、でも待って欲しい。
Decorating[String]も宣言しているのにDecorating[Option[String]]ではほぼ同じようなコードを書いてしまっている。
Decorating[Option[String]]からDecorating[String]のコードを呼び出して再利用したいはず。
こうやれば出来る。
これでStringにもIntにも対応できている。

  implicit def DocoratingOption[T](implicit d: Decorating[T]) = new Decorating[Option[T]] {
    def apply(x: Option[T]) = x.fold("")("OOO " + d(_: T) + " OOO")
  }

  println(decorate(Option("hello")))  // OOO SSS hello SSS OOO
  println(decorate(Option(9)))  // OOO III 9 III OOO
  println(decorate(Option.empty[Int]))  // 何も表示されない

Option[T]のT部分を動的にしないといけないのでimplicit defで実現している。

プログラム全体

最後に今回のプログラムを貼り付けておきます。

object Main extends App {

  def decorate[T](x: T)(implicit deco: Decorating[T]) = deco(x)

  trait Decorating[T] {
    def apply(x: T): String
  }

  implicit val DecoratingString = new Decorating[String] {
    def apply(x: String) = s"SSS $x SSS"
  }

  implicit object DecoratingInt extends Decorating[Int] {
    def apply(x: Int) = s"III $x III"
  }

  implicit def DocoratingOption[T](implicit d: Decorating[T]) = new Decorating[Option[T]] {
    def apply(x: Option[T]) = x.fold("")("OOO " + d(_: T) + " OOO")
  }

  println(decorate("hello"))
  println(decorate(9))
  println(decorate(Option("hello")))
  println(decorate(Option(9)))
  println(decorate(Option.empty[Int]))
}
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3