Skip to content

Instantly share code, notes, and snippets.

@halcat0x15a
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save halcat0x15a/8f4e4ceb2d4e66f811a9 to your computer and use it in GitHub Desktop.
Save halcat0x15a/8f4e4ceb2d4e66f811a9 to your computer and use it in GitHub Desktop.

!SLIDE

Typelevel FizzBuzz in Scala

@halcat0x15a

!SLIDE

型レベルプログラミング

型で計算すること

利点

  • コンパイル時に計算する
  • 型システムの恩恵を得られる

!SLIDE

型レベルFizzBuzzに必要なもの

  • 型レベル自然数
  • 型レベルModulo

shapelessを使う

!SLIDE

FizzBuzz

FizzBuzzの型

  trait FizzBuzz[N <: Nat] {
    type Type
    def show: String
  }

  object FizzBuzz {
    trait Fizz
    trait Buzz
    trait FizzBuzz
  }

!SLIDE

FizzとBuzz

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

implicitの解決

implicitly[FizzBuzz[_5]].show

FizzBuzz[_5]のインスタンスを探索

implicit valueとしてfizzbuzzが見つかる

fizzMod[_5, _3, _0],buzzMod[_5, _5, _0]のインスタンスを要求する

buzzは解決可能

!SLIDE

Priorityの問題

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

Demo

計算と検査

!SLIDE

宣伝

rpscalaというScalaの勉強会があります

Scalaに興味ある型はおこしください

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment