4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Scala] F[_] 高カインド型についてまとめ

Last updated at Posted at 2020-10-25

なぜ

scalaのライブラリを読んでると、F[_]G[F[_]]のような記述が多くて、よく分からんかったので調べた。

ソース

以下の記事を自分なりにまとめただけなので、以下の記事をまずは参照されると。
https://qiita.com/KtheS/items/649fbffcef18c74430f8

valueとは

以下のような純粋な値のことをvalueという。
これが低階層の値である。

val name = "high kind"
val number = 1

proper type

先ほどの例であげると、nameのString型や、numberのInt型、List[String]などをproper typeという。
先ほどのvalueよりも一段、抽象度が上がった表現である。

val name: String = "high kind"
val number: Int = 1
val listStr: List[String] = List("1", "2")
val listInt: List[Int] = List(1, 2)

first-order type

List, Option, Mapのような型をfirst-order typeという。
これらfirst-order type型は、1つ以上のスロットを持つ。(List, Optionなら1つ、Mapなら2つ)
List[_], Option[_], Map[_, _]のことを、type constructorという。

val list: List[_] = List(1, 2)
val opt: Option[_] = Option(1)
val map: Map[_, _] = Map(a -> "1")

さらに一段と抽象度が上がった。

second-order type

F[_]と型を抽象化した型をさらに抽象化したもの
下でいうと、WithMap

型コンストラクタ(F[_])を取る型コンストラクタ(WithMap[])ということで、WithMap[F[_]]を高カインド型という・


trait WithMap[F[_]] {
  
}

F[_]の良い点

F[_]は、1つのスロットを持つ型を抽象化したもの

これによって、メソッドなどを共通化できる。

trait WithMap[F[_]] {
  def map[A, B](fa: F[A])(f: A => B): F[B]
  def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
  def OrElse[A, B](fa: F[B]): F[B]
  def filter[A](fa: F[A])(f: A => Boolean): F[A]

}

上記例のようにメソッドを定義できる。
実態(Listなのか、Optionなのか)によらず、何個のパラメータをとる型なのかで、型を判断できる。

使ってみた


object TypeClassExercise {
  def executeUnwrapped[F[_], A](value: F[A])(implicit objectUnwrapper: ObjectUnwrapper[F]): A = {
    objectUnwrapper.unwrape(value)
  }
  
  // executeUnwrappedのimplicitの糖衣構文
  def executeUnwrapped2[F[_]: ObjectUnwrapper, A](value: F[A]): A = {
    implicitly[ObjectUnwrapper[F]].unwrape(value)
  }
}

trait ObjectUnwrapper[F[_]] {
  def unwrape[A](x: F[A]): A
}

object ObjectUnwrapper {
  implicit def listUnwrapper = new ObjectUnwrapper[List] {
    override def unwrape[A](list: List[A]): A = list.head
  }

  implicit def optionUnwrapper = new ObjectUnwrapper[Option] {
    override def unwrape[A](option: Option[A]): A = option.get
  }
}


object Run extends App {
  val objectUnwrappedListResult = TypeClassExercise.executeUnwrapped(List(1, 2))
  val objectUnwrappedOptionResult = TypeClassExercise.executeUnwrapped(Option(33))
  println(objectUnwrappedListResult)
  println(objectUnwrappedOptionResult)
}
4
2
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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?