!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]].show
FizzBuzz[_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に興味ある型はおこしください