Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
AUXパターンをDOTTYで解決する
自己紹介
麻植泰輔
ScalaMatsuri 座長
Septeni Original, Inc. 技術アドバイザー
7/6 新宿 Geek Lounge で 「Real World Android Akka」を 日本語で 喋ります!
BONX,...
今日のトピック
Dottyの何が嬉しいの? の一部を紹介する
型クラスの型パラメーター同士に依存関係がある場合
Scala 2.x => Auxパターン
Dotty a.k.a. Scala 3.x => ???
型クラス
既存の型に対し、共通の振る舞いを後から定義する (アドホック多相を実現する)
ためのデザインパターン
trait Semigroup[A]{
def append(a1:A,a2:A):A
}
object Semigroup{
im...
DEPENDENT METHOD TYPE
引数の型に依存して、メソッドのシグネチャ(のうち、多くの場合は戻り値の型)を変化させることができる
型クラスと組み合わせるパターンを、Magnet Patternと呼ぶ
引数の型にマグネットがくっつい...
型クラス + DEPENDENT METHOD TYPEの例
Measurableという型クラスを使って、Dependent Method Typeを活用する例
trait Measurable[A]{
type Size
def sizeOf...
型クラスを組み合わせたい…
一つの引数リストに両方入れる?
さっきのSemigroupとMeasurableを組み合わせると、こんな感じ…?
def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A]...
コンパイルが通らない!
同じ引数リスト内の引数を参照できない
scala> def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A], S:Semigroup[M.Size]):
| S.appen...
型クラスを組み合わせたい…(TAKE 2)
複数の暗黙の引数リストを使う?
じゃあ subsequent parameter section ということは、こんな感じ?
def sumSizes[A](a1:A,a2:A)(implicit M...
コンパイルが通らない!
暗黙の引数リストは1つまで
<console>:1: error: an implicit parameter section must be last
def sumSizes[A](a1:A,a2:A)(implic...
型クラスを組み合わせたい…(TAKE 3)
AUXパターン!!
型メンバを型パラメーターへマッピングすることで、暗黙のパラメーターが持つ型パラメーター同士で依存させることができる
trait Measurable[A]{
type Size
d...
コンパイル通る!
…けど、ちょっとhacky。
DOTTY A.K.A. SCALA 3.0
EPFLの小田好先生の研究室で開発を主導
現在pre-alpha
日々アクティブに開発されてるので、
以下、 scalaVersion := "0.1.1-bin-20170511-cc4533d-...
IMPLICIT FUNCTION TYPE
暗黙の引数を取る関数、を型で表現
trait Semigroup[A]{
def append(a1:A,a2:A):A
}
object Semigroup{
implicit val intGr...
MULTIPLE IMPLICIT PARAMETER LISTS
Implicit Function Typeのメソッド表現
いずれかの暗黙の引数 のみ に明示的に値を渡す場合、どの暗黙の引数リストに渡すか決定する構文が欲しい
f.expli...
でも実は...
一つの引数リストに両方入れる
Scala 2.x系ではコンパイルは通らなかったが…
object SemigroupMeasurableSyntax {
def sumSizes[A](a1:A,a2:A)(implicit M...
/(^O^)
defined trait Measurable
defined module Measurable
defined module MeasurableSyntax
defined trait Semigroup
defined ...
結論
DottyになればAuxパターンは不要になる(ハズ) :tada:
型クラスの型パラメーター同士に依存関係がある場合
Scala 2.x => Auxパターン
Dotty a.k.a. Scala 3.x => 共通の暗黙の引数リスト |...
Upcoming SlideShare
Loading in …5
×

AuxパターンをDottyで解決する

1,761 views

Published on

#SyogunMatsuri
#ScalaMatsuri

Published in: Software
  • Be the first to comment

AuxパターンをDottyで解決する

  1. 1. AUXパターンをDOTTYで解決する
  2. 2. 自己紹介 麻植泰輔 ScalaMatsuri 座長 Septeni Original, Inc. 技術アドバイザー 7/6 新宿 Geek Lounge で 「Real World Android Akka」を 日本語で 喋ります! BONX, INC. 所属 将軍家の皆さま、ご協賛ありがとうございました! 来年春頃(予定) ScalaMatsuri 2018 もぜひよろしくお願いします m(_ _)m もしScalaMatsuri経由で入社した方が居た場合、ぜひ記事化させてください @OE_uia
  3. 3. 今日のトピック Dottyの何が嬉しいの? の一部を紹介する 型クラスの型パラメーター同士に依存関係がある場合 Scala 2.x => Auxパターン Dotty a.k.a. Scala 3.x => ???
  4. 4. 型クラス 既存の型に対し、共通の振る舞いを後から定義する (アドホック多相を実現する) ためのデザインパターン trait Semigroup[A]{ def append(a1:A,a2:A):A } object Semigroup{ implicit val intGroup:Semigroup[Int] = new Semigroup[Int]{ def append(a1:Int,a2:Int):Int = a1 + a2 } } object SemigroupSyntax{ def append[A](a1:A, a2:A)(implicit S:Semigroup[A]):A = S.append(a1,a2) } import SemigroupSyntax._ append(1,2) // 3
  5. 5. DEPENDENT METHOD TYPE 引数の型に依存して、メソッドのシグネチャ(のうち、多くの場合は戻り値の型)を変化させることができる 型クラスと組み合わせるパターンを、Magnet Patternと呼ぶ 引数の型にマグネットがくっついて、戻り値の型が変化するイメージ?
  6. 6. 型クラス + DEPENDENT METHOD TYPEの例 Measurableという型クラスを使って、Dependent Method Typeを活用する例 trait Measurable[A]{ type Size def sizeOf(a:A):Size } object Measurable{ implicit val intSize:Measurable[Int] = new Measurable[Int]{ type Size = Int def sizeOf(i:Int):Int = i } implicit def seqSize[A]:Measurable[Seq[A]] = new Measurable[Seq[A]]{ type Size = Int def sizeOf(s:Seq[A]):Int = s.size } } object MeasurableSyntax{ def measure[A](a:A)(implicit M:Measurable[A]):M.Size = M.sizeOf(a) } import MeasurableSyntax._ measure(Seq(1,2,3)) // 3 measure(1) // 1
  7. 7. 型クラスを組み合わせたい… 一つの引数リストに両方入れる? さっきのSemigroupとMeasurableを組み合わせると、こんな感じ…? def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A], S:Semigroup[M.Size]):M.Size S.append(M.sizeOf(a1),M.sizeOf(a2))
  8. 8. コンパイルが通らない! 同じ引数リスト内の引数を参照できない scala> def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A], S:Semigroup[M.Size]): | S.append(M.measure(a1),M.measure(a2)) <console>:32: error: illegal dependent method type: parameter may only be referenced in a subsequent parameter section def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A], S:Semigroup[M.Size]): ^
  9. 9. 型クラスを組み合わせたい…(TAKE 2) 複数の暗黙の引数リストを使う? じゃあ subsequent parameter section ということは、こんな感じ? def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A])(implicit S:Semigroup[M.Size S.append(M.sizeOf(a1),M.sizeOf(a2))
  10. 10. コンパイルが通らない! 暗黙の引数リストは1つまで <console>:1: error: an implicit parameter section must be last def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A])(implicit S:Semigroup[M.Size ^ <console>:1: error: multiple implicit parameter sections are not allowed def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A])(implicit S:Semigroup[M.Size ^
  11. 11. 型クラスを組み合わせたい…(TAKE 3) AUXパターン!! 型メンバを型パラメーターへマッピングすることで、暗黙のパラメーターが持つ型パラメーター同士で依存させることができる trait Measurable[A]{ type Size def sizeOf(a:A):Size } //ここまで同じ object Measurable{ type Aux[A0,B0] = Measurable[A0]{type Size = B0} implicit val intAux:Measurable.Aux[Int,Int] = new Measurable[Int]{ type Size = Int def sizeOf(i:Int):Int = i } } def sumSizes[A,Size](a1:A,a2:A)(implicit M:Measurable.Aux[A,Size], S:Semigroup[Size S.append(M.sizeOf(a1),M.sizeOf(a2))
  12. 12. コンパイル通る! …けど、ちょっとhacky。
  13. 13. DOTTY A.K.A. SCALA 3.0 EPFLの小田好先生の研究室で開発を主導 現在pre-alpha 日々アクティブに開発されてるので、 以下、 scalaVersion := "0.1.1-bin-20170511-cc4533d-NIGHTLY" で実験 Nightly Buildsを試せる!
  14. 14. IMPLICIT FUNCTION TYPE 暗黙の引数を取る関数、を型で表現 trait Semigroup[A]{ def append(a1:A,a2:A):A } object Semigroup{ implicit val intGroup:Semigroup[Int] = new Semigroup[Int]{ def append(a1:Int,a2:Int):Int = a1 + a2 } } //ここまで先程の例と一緒 object SemigroupSyntax{ type Semigroupish[A] = implicit Semigroup[A] => A def append[A](a1:A, a2:A):Semigroupish[A] = {implicit S => S.append(a1,a2)} } object SemigroupMeasurableSyntax { import SemigroupSyntax._ def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A]):Semigroupish[M.Size] = append( }
  15. 15. MULTIPLE IMPLICIT PARAMETER LISTS Implicit Function Typeのメソッド表現 いずれかの暗黙の引数 のみ に明示的に値を渡す場合、どの暗黙の引数リストに渡すか決定する構文が欲しい f.explicitly(...) ... ? まだ提案段階だが、入る可能性高そう? //今(5/11 nightly builds)はまだ出来ないが、そのうちこうやって書けるようになるはず def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A])(implicit S:Semigroup[M.Size S.append(M.sizeOf(a1),M.sizeOf(a2))
  16. 16. でも実は... 一つの引数リストに両方入れる Scala 2.x系ではコンパイルは通らなかったが… object SemigroupMeasurableSyntax { def sumSizes[A](a1:A,a2:A)(implicit M:Measurable[A], S:Semigroup[M.Size]):M.Size S.append(M.sizeOf(a1),M.sizeOf(a2)) }
  17. 17. /(^O^) defined trait Measurable defined module Measurable defined module MeasurableSyntax defined trait Semigroup defined module Semigroup defined module SemigroupSyntax defined module SemigroupMeasurableSyntax <- !?!?!? Dottyではコンパイル通る!!!
  18. 18. 結論 DottyになればAuxパターンは不要になる(ハズ) :tada: 型クラスの型パラメーター同士に依存関係がある場合 Scala 2.x => Auxパターン Dotty a.k.a. Scala 3.x => 共通の暗黙の引数リスト || Implicit Function Type 注: Implicit Function Typeは、Auxパターンをなくすこと「だけ」が目的では有りません 文脈から値を取り出すことを抽象化する、大変強力な構文です をご参照のこと。小田好先生のブログ

×