コンパイル時オペレーション

dottyでは型に対してコンパイル時に行える操作が色々増えている。
特にリテラル型に当たるものは値レベルの操作と遜色無いものが用意されている。
コンパイル時オペレーションの中でもscala.compiletime.ops以下に当たるパッケージを見ていこう。

https://github.com/lampepfl/dotty/tree/master/library/src/scala/compiletime/ops

Intの操作

intリテラルに対して操作を行うことができ、演算があらかた定義されていてびっくりする。
例えば足し算。

import scala.compiletime.ops.int.*

val two: 1 + 1 = 2
summon[2 =:= 1 + 1]

これらはすべてコンパイルが通る。
もちろん計算結果がおかしければコンパイルは通らない。

summon[3 =:= 1 + 1]

//[error] 7 |  summon[3 =:= 1 + 1]
//[error]   |                     ^
//[error]   |                     Cannot prove that (3 : Int) =:= (2 : Int).

他にも四則演算、シフト演算、大小比較、絶対値など色々。
変わり種ではMinやMaxなどが定義されている。

summon[2 =:= Max[1, 2]]
summon[1 =:= Min[1, 2]]

あとは型レベルでStringに変換したり。

summon["1" =:= ToString[1]]

何でもありすぎてビビる。
あとはSが面白い。
これは今まで型レベルで自然数を定義するときに使われていたある自然数の次の数を求める型である。

summon[1 =:= S[0]]

Sは自然数に対してのみ定義されている。

summon[0 =:= S[-1]]

//[error] 12 |  summon[0 =:= S[-1]]
//[error]    |                     ^
//[error]    |      Cannot prove that (0 : Int) =:= compiletime.ops.int.S[(-1 : Int)].

定義自体は非常に簡潔なので一度自分で見てみるとおすすめする。

https://github.com/lampepfl/dotty/blob/master/library/src/scala/compiletime/ops/int.scala

Stringの操作

Intの操作に比べてできることは少なく、足し算のみ。

import scala.compiletime.ops.string.*

summon["hello taro" =:= "hello " + "taro"]

Booleanの操作

否定、排他的論理和、論理和、論理積。

import scala.compiletime.ops.boolean.*

summon[true =:= ![false]]
summon[false =:= ![true]]

summon[false =:= (true ^ true)]
summon[true =:= (false ^ true)]

summon[true =:= (true && true)]
summon[false =:= (true && false)]

summon[true =:= (true || false)]
summon[false =:= (false || false)]

どんな型に対しても行える操作

型が同じかどうかを判定する操作が用意されている。
今まではgeneralized type constraint(=:=、<:<)でインスタンスが見つかれば〜という感じだったが、これはBooleanのサブ型を返してくる。

import scala.compiletime.ops.int.*
import scala.compiletime.ops.any.*

summon[true =:= (2 == S[1])]
summon[false =:= (2 == S[2])]
リテラル型(literal type) 型レベル多項式の微分 [初級-中級向け]Scala基本APIを完全に理解するシリーズ② -Either編-
View Comments
There are currently no comments.