SlideShare uma empresa Scribd logo
1 de 18
Baixar para ler offline
AUXパターンをDOTTYで解決する
自己紹介
麻植泰輔
ScalaMatsuri 座長
Septeni Original, Inc. 技術アドバイザー
7/6 新宿 Geek Lounge で 「Real World Android Akka」を 日本語で 喋ります!
BONX, INC. 所属
将軍家の皆さま、ご協賛ありがとうございました!
来年春頃(予定) ScalaMatsuri 2018 もぜひよろしくお願いします m(_ _)m
もしScalaMatsuri経由で入社した方が居た場合、ぜひ記事化させてください
@OE_uia
今日のトピック
Dottyの何が嬉しいの? の一部を紹介する
型クラスの型パラメーター同士に依存関係がある場合
Scala 2.x => Auxパターン
Dotty a.k.a. Scala 3.x => ???
型クラス
既存の型に対し、共通の振る舞いを後から定義する (アドホック多相を実現する)
ためのデザインパターン
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
DEPENDENT METHOD TYPE
引数の型に依存して、メソッドのシグネチャ(のうち、多くの場合は戻り値の型)を変化させることができる
型クラスと組み合わせるパターンを、Magnet Patternと呼ぶ
引数の型にマグネットがくっついて、戻り値の型が変化するイメージ?
型クラス + 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
型クラスを組み合わせたい…
一つの引数リストに両方入れる?
さっきの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))
コンパイルが通らない!
同じ引数リスト内の引数を参照できない
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]):
^
型クラスを組み合わせたい…(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))
コンパイルが通らない!
暗黙の引数リストは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
^
型クラスを組み合わせたい…(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))
コンパイル通る!
…けど、ちょっとhacky。
DOTTY A.K.A. SCALA 3.0
EPFLの小田好先生の研究室で開発を主導
現在pre-alpha
日々アクティブに開発されてるので、
以下、 scalaVersion := "0.1.1-bin-20170511-cc4533d-NIGHTLY" で実験
Nightly Buildsを試せる!
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(
}
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))
でも実は...
一つの引数リストに両方入れる
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))
}
/(^O^)
defined trait Measurable
defined module Measurable
defined module MeasurableSyntax
defined trait Semigroup
defined module Semigroup
defined module SemigroupSyntax
defined module SemigroupMeasurableSyntax <- !?!?!?
Dottyではコンパイル通る!!!
結論
DottyになればAuxパターンは不要になる(ハズ) :tada:
型クラスの型パラメーター同士に依存関係がある場合
Scala 2.x => Auxパターン
Dotty a.k.a. Scala 3.x => 共通の暗黙の引数リスト || Implicit Function Type
注: Implicit Function Typeは、Auxパターンをなくすこと「だけ」が目的では有りません
文脈から値を取り出すことを抽象化する、大変強力な構文です
をご参照のこと。小田好先生のブログ

Mais conteúdo relacionado

Mais procurados

ジェネリクスの基礎と クラス設計への応用
ジェネリクスの基礎とクラス設計への応用ジェネリクスの基礎とクラス設計への応用
ジェネリクスの基礎と クラス設計への応用
nagise
 
Sns suite presentation
Sns suite presentationSns suite presentation
Sns suite presentation
Jason Namkung
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
Hiroshi Ono
 
実務者のためのかんたんScalaz
実務者のためのかんたんScalaz実務者のためのかんたんScalaz
実務者のためのかんたんScalaz
Tomoharu ASAMI
 

Mais procurados (19)

ジェネリクスの基礎と応用 JJUG CCC 2012 Fall
ジェネリクスの基礎と応用 JJUG CCC 2012 Fallジェネリクスの基礎と応用 JJUG CCC 2012 Fall
ジェネリクスの基礎と応用 JJUG CCC 2012 Fall
 
ジェネリクスの基礎と クラス設計への応用
ジェネリクスの基礎とクラス設計への応用ジェネリクスの基礎とクラス設計への応用
ジェネリクスの基礎と クラス設計への応用
 
Material
MaterialMaterial
Material
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Phantom Type in Scala
Phantom Type in ScalaPhantom Type in Scala
Phantom Type in Scala
 
Algebraic DP: 動的計画法を書きやすく
Algebraic DP: 動的計画法を書きやすくAlgebraic DP: 動的計画法を書きやすく
Algebraic DP: 動的計画法を書きやすく
 
Sns suite presentation
Sns suite presentationSns suite presentation
Sns suite presentation
 
Pythonintro
PythonintroPythonintro
Pythonintro
 
Thinking in Cats
Thinking in CatsThinking in Cats
Thinking in Cats
 
大人のお型付け
大人のお型付け大人のお型付け
大人のお型付け
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
Implicit Explicit Scala
Implicit Explicit ScalaImplicit Explicit Scala
Implicit Explicit Scala
 
Haskell超入門 Part.1
Haskell超入門 Part.1Haskell超入門 Part.1
Haskell超入門 Part.1
 
磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!
 
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorpSwift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
 
Rpscala2011 0601
Rpscala2011 0601Rpscala2011 0601
Rpscala2011 0601
 
実務者のためのかんたんScalaz
実務者のためのかんたんScalaz実務者のためのかんたんScalaz
実務者のためのかんたんScalaz
 

Mais de Taisuke Oe (10)

プレScalaMatsuri2019「スピーカー入門」
プレScalaMatsuri2019「スピーカー入門」プレScalaMatsuri2019「スピーカー入門」
プレScalaMatsuri2019「スピーカー入門」
 
How to start functional programming (in Scala): Day1
How to start functional programming (in Scala): Day1How to start functional programming (in Scala): Day1
How to start functional programming (in Scala): Day1
 
Monix Taskが便利だという話
Monix Taskが便利だという話Monix Taskが便利だという話
Monix Taskが便利だという話
 
How to get along with implicits
How to get along with implicits How to get along with implicits
How to get along with implicits
 
Real World Android Akka - 日本語版
Real World Android Akka - 日本語版Real World Android Akka - 日本語版
Real World Android Akka - 日本語版
 
Real World Android Akka
Real World Android AkkaReal World Android Akka
Real World Android Akka
 
Real world android akka
Real world android akkaReal world android akka
Real world android akka
 
多相な関数の定義から学ぶ、型クラスデザインパターン
多相な関数の定義から学ぶ、型クラスデザインパターン多相な関数の定義から学ぶ、型クラスデザインパターン
多相な関数の定義から学ぶ、型クラスデザインパターン
 
Android BLEのつらみを予防するTips
Android BLEのつらみを予防するTipsAndroid BLEのつらみを予防するTips
Android BLEのつらみを予防するTips
 
BONXを支える技術:Bluetooth編 ~Bluetoothを120%使い倒す方法~
BONXを支える技術:Bluetooth編 ~Bluetoothを120%使い倒す方法~BONXを支える技術:Bluetooth編 ~Bluetoothを120%使い倒す方法~
BONXを支える技術:Bluetooth編 ~Bluetoothを120%使い倒す方法~
 

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