見た目通りで、あまり難しくないので、特に説明することがない。 macroさえ使わずに書けますね。 shapelessにあったような色々な機能が標準で装備されています。
みなさん、Match Type使ってもっと複雑な色々な計算書いてみましょう。
ちなみに、この単純な実装だと、大きい数渡すと(コンパイル時に)大変なことになるのでご注意ください。
plugins.sbt
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.4.1")
build.sbt
scalaVersion := "0.26.0-RC1"
Main.scala
package example import scala.compiletime.ops.int.{-, +} import scala.compiletime.testing.{typeChecks, typeCheckErrors, Error, ErrorKind} type Fibonacci[A <: Int] <: Int = A match { case 0 => 0 case 1 => 1 case _ => Fibonacci[A - 1] + Fibonacci[A - 2] } object Main { def main(args: Array[String]): Unit = { val _: Fibonacci[10] = 55 // success. compile fail if other value assert(typeChecks("val _: Fibonacci[10] = 55")) assert(typeChecks("val _: Fibonacci[10] = 4") == false) val result = typeCheckErrors("val _: Fibonacci[10] = 4") println(result) assert( result == List( Error( message = "Found: (4 : Int)\nRequired: (55 : Int)", lineContent = "val _: Fibonacci[10] = 4", column = 23, kind = ErrorKind.Typer ) ) ) } }
あと、上記の定義があった場合に、こういうのを定義することも可能です。
transparent inline def fibonacci[A <: Int]: Fibonacci[A] =
valueOf[Fibonacci[A]]
- transparent inlineは、Scala 2のwhitebox macroみたいにコンパイル時に、指定した戻り型のsub type返せるやつ
- valueOfはScala 2.13にもある、その型の値を返せるやつ(Scala 2.13でも
valueOf[3]
とか出来る)
その他詳細は以下を見てください
- https://dotty.epfl.ch/docs/reference/new-types/match-types.html
- https://github.com/lampepfl/dotty/blob/64a239f62ce8a9528b3a4e2c52349180629ef570/docs/docs/reference/new-types/match-types.md
- https://github.com/lampepfl/dotty/tree/64a239f62ce8a9528b3a4e2c52349180629ef570/library/src/scala/compiletime/testing
- https://github.com/lampepfl/dotty/blob/64a239f62ce8a9528b3a4e2c52349180629ef570/library/src/scala/compiletime/ops/package.scala