SlideShare ist ein Scribd-Unternehmen logo
1 von 15
Downloaden Sie, um offline zu lesen
幽
霊
型
の
紹
介
A.J.A.社内勉強会 6/23
自己紹介
● 名前:阿部晃典
● 言語:OCaml, Perl, JavaScript, C/C++, Go, Java, PHP, LaTeX, Octave, etc.
● 専門:プログラミング言語理論
○ 大学〜大学院1年くらいまで、幽霊型を使った線形代数ライブラリを作成
■ Sized Linear Algebra Package (SLAP): http://akabe.github.io/slap/
○ C++ テンプレート(メタプログラミング)を出力するコンパイラを書いた
■ EvilML (a compiler from ML to C++ template): http://akabe.github.io/evilml/
● 趣味:機械学習
幽霊型 (phantom type) とは...
● プログラムのバグをコンパイル時に発見する手法
○ テスト工数削減
○ プログラムの信頼性向上
○ 使ってて楽しい
● プログラムに型が付く ⇒ ある種のバグは存在しないことを証明
○ 「ある種のバグ」の範囲は幽霊型トリックによって色々
■ 例1:行列演算の次元の整合性の検査 [Eaton ‘06, Abe & Sumii ‘15]
■ 例2:配列アクセスの境界検査 [Kiselyov & Shan ‘07]
■ 例3:型安全な DSL (Domain Specific Language)
● C 関数のバインディング in Standard ML [Blume ‘01]
● JavaScript のバインディング in OCaml, Haskell (js_of_ocaml, ghcjs)
● Rogue (MongoDB in Scala)
簡
単
な
例
例:多重エンコードの検出
● enc 関数の仕様
○ 入力:普通の(エンコードされていない)文字列
○ 出力:エンコード済みの文字列
● enc 関数の型
○ 引数型:Str[Normal] (= String)
○ 戻り値型:Str[Encoded] (= String)
val x = "Hello, World!”
val y = encode(x) // これは OK
val z = encode(y) // これは型エラーにしたい
ポイント①
プログラムの
詳細な仕様を型で表現
素朴な実装
class Str [T] (val str: String)
// T は幽霊型変数:内部では使われない型変数
trait Normal // 幽霊型(値を持たない型)
trait Encoded // これも幽霊型
def encode(x: Str[Normal]) = new Str[Encoded](...)
// encode: (x: Str[Normal]): Str[Encoded]
val x = Str[Normal](“Hello, World”)
val y = encode(x) // これは OK (y: Str[Encoded])
val z = encode(y) // 型エラー
ポイント②
幽霊型変数に
仕様を表す型を入れる
素朴な実装の問題点
class Str [T] (val str: String)
trait Normal
trait Encoded
def encode(x: Str[Normal]) = new Str[Encoded](...)
val x = Str[Normal](“Hello, World”)
val y = encode(x) // y: Str[Encoded]
val z = Str[Normal](y.str) // z: Str[Normal]
val w = encode(z) // 二重エンコードできてしまう!
エンコード済みの文字列
なのに Str[Normal] の
型付いている
コンストラクタの隠蔽
object SafeStr {
class Str [T] private[SafeStr]
(private[SafeStr] val str: String)
trait Normal
trait Encoded
def create(x: String) = new Str[Normal](x)
def encode(x: Str[Normal]) = new Str[Encoded](...)
}
val x = create(“Hello, World”)
val y = encode(x) // y: Str[Encoded]
val z = Str[Normal](y.str) // Error!
val w = encode(y) // type mismatch
ポイント③
コンストラクタと
フィールドを隠蔽する
ポイントのおさらい
object SafeStr {
class Str [T] private[SafeStr]
(private[SafeStr] val str: String)
trait Normal
trait Encoded
def create(x: String) = new Str[Normal](x)
def encode(x: Str[Normal]) = new Str[Encoded](...)
// encode (x: Str[Normal]): Str[Encoded]
}
ポイント③
コンストラクタと
フィールドを隠蔽する
ポイント②
幽霊型変数に
仕様を表す型を入れる
ポイント①
プログラムの
詳細な仕様を型で表現
も
う
少
し
高
度
な
例
型レベル自然数 (Peano 形式)
class Nat[N] (val n: Int) // Nat[N]=Int
trait Z // zero
trait S[N] // successor (n+1)
val zero = new Nat[Z](0) // zero: Nat[N]
def succ[N](n: Nat[N]) = new Nat[S[N]](n.n+1)
// succ: (n: Nat[N]): Nat[S[N]]
def pred[N](n: Nat[S[N]]) = new Nat[N](n.n-1)
// pred: (n: Nat[S[N]]): Nat[N]
val x = zero // x: Nat[Z]
val y = succ(x) // y: Nat[S[Z]]
val z = succ(y) // z: Nat[S[S[Z]]]
型レベル自然数による安全性
class Nat[N] (val n: Int) // Nat[N]=Int
trait Z // zero
trait S[N] // successor (n+1)
val zero = new Nat[Z](0) // zero: Nat[N]
def succ[N](n: Nat[N]) = new Nat[S[N]](n.n+1)
// succ: (n: Nat[N]): Nat[S[N]]
def pred[N](n: Nat[S[N]]) = new Nat[N](n.n-1)
// pred: (n: Nat[S[N]]): Nat[N]
val x = pred(succ(zero)) // x: Nat[Z]
val y = pred(zero) // 型エラー(非負数であることを保証)
zero == succ(zero) // 型エラー(値の等しさの保証)
型レベル自然数の用例:型安全 head, tail, zip
class SList[N, E] (val list: List[E]) // SList[N,E]=List[E]
trait Z // zero
trait S[N] // successor (n+1)
def empty[E]: SList[Z, E] = ...
def cons[N, E] (a:E, x: SList[N, E]): SList[S[N], E] = ...
val x = cons(“baz”, empty[String]) // x: SList[S[Z], String]
val y = tail(x) // y: SList[Z, String]
val z = tail(y) // 型エラー(空リストは tail, head 不可)
def head[N, E] (x: SList[S[N], E]): E = ...
def tail[N, E] (x: SList[S[N], E]): SList[N, E] = ...
型レベル自然数の用例:型安全 head, tail, zip
class SList[N, E] (val list: List[E]) // SList[N,E]=List[E]
trait Z // zero
trait S[N] // successor (n+1)
def empty[E]: SList[Z, E] = ...
def cons[N, E] (a:E, x: SList[N, E]): SList[S[N], E] = ...
val x = cons(“baz”, empty[String]) // x: SList[S[Z],String]
val y = zip(x, x) // y: SList[S[Z], (String, String)]
val z = zip(x, empty[String]) // 型エラー(長さの等しさを保証)
def zip[N,E] (x: SList[N,E], y: SList[N,E]): SList[N,E] =
まとめ
● プログラムのバグをコンパイル時に発見する手法
○ ポイント1:プログラムの詳細な仕様を型で表現
○ ポイント2:幽霊型変数に仕様を表す型を入れる
○ ポイント3:コンストラクタを隠蔽して、幽霊型変数に入る型を制限
● プログラムに型が付く ⇒ ある種のバグは存在しないことを証明
○ 「ある種のバグ」の範囲は幽霊型トリックによって色々
■ SafeStr の例:多重エンコード
■ SafeList の例:空リストへの head, tail、異なる長さのリストの zip (http://bit.
ly/ScalaSafeList)
■ 例1:行列演算の次元の整合性の検査 [Eaton ‘06, Abe & Sumii ‘15]
■ 例2:配列アクセスの境界検査 [Kiselyov & Shan ‘07]
■ 例3:型安全な DSL (Domain Specific Language) [Blume’01, etc.]

Weitere ähnliche Inhalte

Andere mochten auch

20161110 tristan 広告ランキング
20161110 tristan 広告ランキング20161110 tristan 広告ランキング
20161110 tristan 広告ランキングTristan Irvine
 
Performance optimisation with GraphQL
Performance optimisation with GraphQLPerformance optimisation with GraphQL
Performance optimisation with GraphQLyann_s
 
課題を解決するためにやりたいこと
課題を解決するためにやりたいこと課題を解決するためにやりたいこと
課題を解決するためにやりたいことtatsuya kiyono
 
フロントでのGraphQL
フロントでのGraphQLフロントでのGraphQL
フロントでのGraphQLChao Li
 
GenisysでTableauを導入した話
GenisysでTableauを導入した話GenisysでTableauを導入した話
GenisysでTableauを導入した話Yuki Katada
 
ニューラルネットと深層学習の歴史
ニューラルネットと深層学習の歴史ニューラルネットと深層学習の歴史
ニューラルネットと深層学習の歴史Akinori Abe
 

Andere mochten auch (7)

20161110 tristan 広告ランキング
20161110 tristan 広告ランキング20161110 tristan 広告ランキング
20161110 tristan 広告ランキング
 
Performance optimisation with GraphQL
Performance optimisation with GraphQLPerformance optimisation with GraphQL
Performance optimisation with GraphQL
 
課題を解決するためにやりたいこと
課題を解決するためにやりたいこと課題を解決するためにやりたいこと
課題を解決するためにやりたいこと
 
フロントでのGraphQL
フロントでのGraphQLフロントでのGraphQL
フロントでのGraphQL
 
GenisysでTableauを導入した話
GenisysでTableauを導入した話GenisysでTableauを導入した話
GenisysでTableauを導入した話
 
ニューラルネットと深層学習の歴史
ニューラルネットと深層学習の歴史ニューラルネットと深層学習の歴史
ニューラルネットと深層学習の歴史
 
Phantom Type in Scala
Phantom Type in ScalaPhantom Type in Scala
Phantom Type in Scala
 

Kürzlich hochgeladen

知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptxsn679259
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Gamesatsushi061452
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルCRI Japan, Inc.
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsWSO2
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video UnderstandingToru Tamaki
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...Toru Tamaki
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイスCRI Japan, Inc.
 

Kürzlich hochgeladen (10)

知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 

幽霊型の紹介(サイバーエージェントA.J.A.社内勉強会 2016.6.23)

  • 2. 自己紹介 ● 名前:阿部晃典 ● 言語:OCaml, Perl, JavaScript, C/C++, Go, Java, PHP, LaTeX, Octave, etc. ● 専門:プログラミング言語理論 ○ 大学〜大学院1年くらいまで、幽霊型を使った線形代数ライブラリを作成 ■ Sized Linear Algebra Package (SLAP): http://akabe.github.io/slap/ ○ C++ テンプレート(メタプログラミング)を出力するコンパイラを書いた ■ EvilML (a compiler from ML to C++ template): http://akabe.github.io/evilml/ ● 趣味:機械学習
  • 3. 幽霊型 (phantom type) とは... ● プログラムのバグをコンパイル時に発見する手法 ○ テスト工数削減 ○ プログラムの信頼性向上 ○ 使ってて楽しい ● プログラムに型が付く ⇒ ある種のバグは存在しないことを証明 ○ 「ある種のバグ」の範囲は幽霊型トリックによって色々 ■ 例1:行列演算の次元の整合性の検査 [Eaton ‘06, Abe & Sumii ‘15] ■ 例2:配列アクセスの境界検査 [Kiselyov & Shan ‘07] ■ 例3:型安全な DSL (Domain Specific Language) ● C 関数のバインディング in Standard ML [Blume ‘01] ● JavaScript のバインディング in OCaml, Haskell (js_of_ocaml, ghcjs) ● Rogue (MongoDB in Scala)
  • 5. 例:多重エンコードの検出 ● enc 関数の仕様 ○ 入力:普通の(エンコードされていない)文字列 ○ 出力:エンコード済みの文字列 ● enc 関数の型 ○ 引数型:Str[Normal] (= String) ○ 戻り値型:Str[Encoded] (= String) val x = "Hello, World!” val y = encode(x) // これは OK val z = encode(y) // これは型エラーにしたい ポイント① プログラムの 詳細な仕様を型で表現
  • 6. 素朴な実装 class Str [T] (val str: String) // T は幽霊型変数:内部では使われない型変数 trait Normal // 幽霊型(値を持たない型) trait Encoded // これも幽霊型 def encode(x: Str[Normal]) = new Str[Encoded](...) // encode: (x: Str[Normal]): Str[Encoded] val x = Str[Normal](“Hello, World”) val y = encode(x) // これは OK (y: Str[Encoded]) val z = encode(y) // 型エラー ポイント② 幽霊型変数に 仕様を表す型を入れる
  • 7. 素朴な実装の問題点 class Str [T] (val str: String) trait Normal trait Encoded def encode(x: Str[Normal]) = new Str[Encoded](...) val x = Str[Normal](“Hello, World”) val y = encode(x) // y: Str[Encoded] val z = Str[Normal](y.str) // z: Str[Normal] val w = encode(z) // 二重エンコードできてしまう! エンコード済みの文字列 なのに Str[Normal] の 型付いている
  • 8. コンストラクタの隠蔽 object SafeStr { class Str [T] private[SafeStr] (private[SafeStr] val str: String) trait Normal trait Encoded def create(x: String) = new Str[Normal](x) def encode(x: Str[Normal]) = new Str[Encoded](...) } val x = create(“Hello, World”) val y = encode(x) // y: Str[Encoded] val z = Str[Normal](y.str) // Error! val w = encode(y) // type mismatch ポイント③ コンストラクタと フィールドを隠蔽する
  • 9. ポイントのおさらい object SafeStr { class Str [T] private[SafeStr] (private[SafeStr] val str: String) trait Normal trait Encoded def create(x: String) = new Str[Normal](x) def encode(x: Str[Normal]) = new Str[Encoded](...) // encode (x: Str[Normal]): Str[Encoded] } ポイント③ コンストラクタと フィールドを隠蔽する ポイント② 幽霊型変数に 仕様を表す型を入れる ポイント① プログラムの 詳細な仕様を型で表現
  • 11. 型レベル自然数 (Peano 形式) class Nat[N] (val n: Int) // Nat[N]=Int trait Z // zero trait S[N] // successor (n+1) val zero = new Nat[Z](0) // zero: Nat[N] def succ[N](n: Nat[N]) = new Nat[S[N]](n.n+1) // succ: (n: Nat[N]): Nat[S[N]] def pred[N](n: Nat[S[N]]) = new Nat[N](n.n-1) // pred: (n: Nat[S[N]]): Nat[N] val x = zero // x: Nat[Z] val y = succ(x) // y: Nat[S[Z]] val z = succ(y) // z: Nat[S[S[Z]]]
  • 12. 型レベル自然数による安全性 class Nat[N] (val n: Int) // Nat[N]=Int trait Z // zero trait S[N] // successor (n+1) val zero = new Nat[Z](0) // zero: Nat[N] def succ[N](n: Nat[N]) = new Nat[S[N]](n.n+1) // succ: (n: Nat[N]): Nat[S[N]] def pred[N](n: Nat[S[N]]) = new Nat[N](n.n-1) // pred: (n: Nat[S[N]]): Nat[N] val x = pred(succ(zero)) // x: Nat[Z] val y = pred(zero) // 型エラー(非負数であることを保証) zero == succ(zero) // 型エラー(値の等しさの保証)
  • 13. 型レベル自然数の用例:型安全 head, tail, zip class SList[N, E] (val list: List[E]) // SList[N,E]=List[E] trait Z // zero trait S[N] // successor (n+1) def empty[E]: SList[Z, E] = ... def cons[N, E] (a:E, x: SList[N, E]): SList[S[N], E] = ... val x = cons(“baz”, empty[String]) // x: SList[S[Z], String] val y = tail(x) // y: SList[Z, String] val z = tail(y) // 型エラー(空リストは tail, head 不可) def head[N, E] (x: SList[S[N], E]): E = ... def tail[N, E] (x: SList[S[N], E]): SList[N, E] = ...
  • 14. 型レベル自然数の用例:型安全 head, tail, zip class SList[N, E] (val list: List[E]) // SList[N,E]=List[E] trait Z // zero trait S[N] // successor (n+1) def empty[E]: SList[Z, E] = ... def cons[N, E] (a:E, x: SList[N, E]): SList[S[N], E] = ... val x = cons(“baz”, empty[String]) // x: SList[S[Z],String] val y = zip(x, x) // y: SList[S[Z], (String, String)] val z = zip(x, empty[String]) // 型エラー(長さの等しさを保証) def zip[N,E] (x: SList[N,E], y: SList[N,E]): SList[N,E] =
  • 15. まとめ ● プログラムのバグをコンパイル時に発見する手法 ○ ポイント1:プログラムの詳細な仕様を型で表現 ○ ポイント2:幽霊型変数に仕様を表す型を入れる ○ ポイント3:コンストラクタを隠蔽して、幽霊型変数に入る型を制限 ● プログラムに型が付く ⇒ ある種のバグは存在しないことを証明 ○ 「ある種のバグ」の範囲は幽霊型トリックによって色々 ■ SafeStr の例:多重エンコード ■ SafeList の例:空リストへの head, tail、異なる長さのリストの zip (http://bit. ly/ScalaSafeList) ■ 例1:行列演算の次元の整合性の検査 [Eaton ‘06, Abe & Sumii ‘15] ■ 例2:配列アクセスの境界検査 [Kiselyov & Shan ‘07] ■ 例3:型安全な DSL (Domain Specific Language) [Blume’01, etc.]