!SLIDE
!SLIDE
型で計算すること
- コンパイル時に計算する
- 型システムの恩恵を得られる
!SLIDE
- 型レベル自然数
- 型レベルModulo
shapelessを使う
!SLIDE
FizzBuzzの型
trait FizzBuzz[N <: Nat] {
type Type
def show: String
}
object FizzBuzz {
trait Fizz
trait Buzz
trait FizzBuzz
}!SLIDE
implicitを使ってインスタンスを定義する
trait FizzBuzzImplicits {
implicit def fizz[N <: Nat](implicit mod: Mod.Aux[N, _3, _0]) = new FizzBuzz[N] {
type Type = FizzBuzz.Fizz
def show = "Fizz"
}
implicit def buzz[N <: Nat](implicit mod: Mod.Aux[N, _5, _0]) = new FizzBuzz[N] {
type Type = FizzBuzz.Buzz
def show = "Buzz"
}
}
object FizzBuzz extends FizzBuzzImplicits { ... }!SLIDE
implicitly[FizzBuzz[_5]].showFizzBuzz[_5]のインスタンスを探索
implicit valueとしてfizzとbuzzが見つかる
fizzはMod[_5, _3, _0],buzzはMod[_5, _5, _0]のインスタンスを要求する
buzzは解決可能
!SLIDE
FizzとBuzzよりもFizzBuzzを優先して導出しなければいけない
Scalaはimplicitの解決に階層が考慮される
trait FizzBuzzLowPriorityImplicits {
implicit def fizz[N <: Nat](implicit mod: Mod.Aux[N, _3, _0]) = ...
implicit def buzz[N <: Nat](implicit mod: Mod.Aux[N, _5, _0]) = ...
}
trait FizzBuzzImplicits extends FizzBuzzLowPriorityImplicits {
implicit def fizzbuzz[N <: Nat](implicit mod: Mod.Aux[N, _15, _0]) = new FizzBuzz[N] {
type Type = FizzBuzz.FizzBuzz
def show = "FizzBuzz"
}
}!SLIDE
数値の場合も同様にして定義する
trait FizzBuzzLowestPriorityImplicit {
implicit def number[N <: Nat](implicit int: ToInt[N]) = new FizzBuzz[N] {
type Type = N
def show = Nat.toInt[N].toString
}
}
trait FizzBuzzLowPriorityImplicits extends FizzBuzzLowestPriorityImplicit { ... }!SLIDE
計算と検査
!SLIDE
rpscalaというScalaの勉強会があります
Scalaに興味ある型はおこしください