SlideShare a Scribd company logo
1 of 37
Download to read offline
Frege,
What a Non-strict Language
チェシャ猫 (@y_taka_23)
NL 名古屋 (2016/04/16)
自己紹介
● 名前 : チェシャ猫
○ Twitter: @y_taka_23
○ GitHub: y-taka-23
● 好きなもの
○ Haskell
○ 形式手法 (Coq, Alloy, SPIN, etc...)
● 自称 Frege エバンジェリスト
本日の内容
● JVM 言語 Frege の概要
○ 基本的な特徴
○ Haskell との比較
● Java コード生成と非正格評価
○ コンパイルの仕組み
○ 評価戦略のマッピング
1. JVM 言語 Frege の概要
“Frege is a Haskell for JVM”
Frege のエッセンス
● 純粋・非正格評価な関数型言語
○ 本日のメイントピック
● 強い静的型付け
○ Hindley-Milner 型推論 + Rank-N types
● モナドによる Java の呼び出し
○ 歌舞伎座.tech #9 での発表スライド参照
○ 「すごい Frege たのしく学ぼう!」で検索
Q: どんな文法?
Hello, Frege
module Hello where
greeting :: String -> String
greeting name = “Hello, “ ++ name
main :: [String] -> IO ()
main args = do
putStrLn $ greeting “World”
Hello, Frege
module Hello where
greeting :: String -> String
greeting name = “Hello, “ ++ name
main :: [String] -> IO ()
main args = do
putStrLn $ greeting “World”
A: ほぼ Haskell
『すごい Haskell』翻訳実験
● 全サンプルコードを Frege に
○ https://github.com/y-taka-23/learn-you-a-frege
● だいたい丸写しでコンパイルが通る
○ 構文論的には Haskell 2010 互換
2. Java コード生成と非正格評価
Frege のコンパイル
● コンパイラ自身も Frege 実装
● JVM 系ビルドツールが利用可
○ Gradle, Maven, sbt. Leiningen, Bazel
● コンパイルすると Java ソースコードに
○ あくまでも中間生成コードで可読性低
○ 最新版 v3.24 で生成ロジックが変更
Hello again, Frege
module Hello where
greeting :: String -> String
greeting name = “Hello, “ ++ name
main :: [String] -> IO ()
main args = do
putStrLn $ greeting “World”
Hello again, Frege
module Hello where
greeting :: String -> String
greeting name = “Hello, “ ++ name
main :: [String] -> IO ()
main args = do
putStrLn $ greeting “World”
Hello again, Frege
module Hello where
greeting :: String -> String
greeting name = “Hello, “ ++ name
main :: [String] -> IO ()
main args = do
putStrLn $ greeting “World”
public static void main(String[] args) {...}
Frege の型 = Java の型?
Frege によるたらい回し関数
tarai :: Int -> Int -> Int -> Int
tarai x y z =
if x <= y
then y
else tarai (tarai (x - 1) y z)
(tarai (y - 1) z x)
(tarai (z - 1) x y)
予想される Java コード
static int tarai(int x, int y, int z) {
if (x <= y) {
return y;
} else {
return tarai(
tarai(x - 1, y, z),
tarai(y - 1, z, x),
tarai(z - 1, x, y));
}
}
コンパイルしてみる
生成されるコードの骨子
static int tarai(int x, int y, Lazy<Integer> z) {
if (x <= y) {
return y;
} else {
return tarai(
tarai(x - 1, y, z),
tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)),
Thunk.<Integer>shared(
(Lazy<Integer>)(() -> tarai(
(int)z.call() - 1, x,
Thunk.<Integer>lazy(y))))
);
}
}
意外と複雑だった
評価戦略のマッピング
● Haskell の非正格評価を Java 上で再現
● ここで関連する要素は主に 3 つ
○ frege.run8.Lazy<T>
○ frege.run8.Box<T>
○ frege.run8.Thunk<T>
frege.run8.Lazy<T>
● Callable のサブインタフェース
○ call() メソッドで値を取得
● R 型の式の評価を遅延させる
○ 役割は Supplier<R> に類似
● Frege の代数的データ型や関数は
デフォルトで Lazy の実装クラスに
frege.run8.Lazy<T>
static int tarai(int x, int y, Lazy<Integer> z) {
if (x <= y) {
return y;
} else {
return tarai(
tarai(x - 1, y, z),
tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)),
Thunk.<Integer>shared(
(Lazy<Integer>)(() -> tarai(
(int)z.call() - 1, x,
Thunk.<Integer>lazy(y))))
);
}
}
frege.run8.Lazy<T>
static int tarai(int x, int y, Lazy<Integer> z) {
if (x <= y) {
return y;
} else {
return tarai(
tarai(x - 1, y, z),
tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)),
Thunk.<Integer>shared(
(Lazy<Integer>)(() -> tarai(
(int)z.call() - 1, x,
Thunk.<Integer>lazy(y))))
);
}
}
frege.run8.Box<T>
● Lazy の実装クラスその 1
● Thunk.<T>lazy(x) で生成
● Lazy になっていない型のラッパー
○ 役割は IntSupplier などと同様
○ call() されるとラップされている値を返す
frege.run8.Box<T>
static int tarai(int x, int y, Lazy<Integer> z) {
if (x <= y) {
return y;
} else {
return tarai(
tarai(x - 1, y, z),
tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)),
Thunk.<Integer>shared(
(Lazy<Integer>)(() -> tarai(
(int)z.call() - 1, x,
Thunk.<Integer>lazy(y))))
);
}
}
frege.run8.Box<T>
static int tarai(int x, int y, Lazy<Integer> z) {
if (x <= y) {
return y;
} else {
return tarai(
tarai(x - 1, y, z),
tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)),
Thunk.<Integer>shared(
(Lazy<Integer>)(() -> tarai(
(int)z.call() - 1, x,
Thunk.<Integer>lazy(y))))
);
}
}
frege.run8.Thunk<T>
● Lazy の実装クラスその 2
● Thunk.<T>shared(x)で生成
● Call-by-need を実現
○ x が共有可能なら shared(x) は x を返す
○ 初めて call() されると内部に値を保持
○ 次に call() された際にはその値を返す
frege.run8.Thunk<T>
static int tarai(int x, int y, Lazy<Integer> z) {
if (x <= y) {
return y;
} else {
return tarai(
tarai(x - 1, y, z),
tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)),
Thunk.<Integer>shared(
(Lazy<Integer>)(() -> tarai(
(int)z.call() - 1, x,
Thunk.<Integer>lazy(y))))
);
}
}
McCarthy による変種
tak :: Int -> Int -> Int -> Int
tak x y z =
if x <= y
then z
else tak (tak (x - 1) y z)
(tak (y - 1) z x)
(tak (z - 1) x y)
McCarthy による変種
tak :: Int -> Int -> Int -> Int
tak x y z =
if x <= y
then z
else tak (tak (x - 1) y z)
(tak (y - 1) z x)
(tak (z - 1) x y)
McCarthy 版から生成されるコード
static int tak(int x, int y, int z) {
if (x <= y) {
return z;
} else {
return tak(
tak(x - 1, y, z),
tak(y - 1, z, x),
tak(z - 1, x, y));
}
}
McCarthy 版から生成されるコード
static int tak(int x, int y, int z) {
if (x <= y) {
return z;
} else {
return tak(
tak(x - 1, y, z),
tak(y - 1, z, x),
tak(z - 1, x, y));
}
}
まとめ
● Frege は JVM のための Haskell
○ 構文は Haskell そのまま
○ JVM 系ビルドツールが使用可能
● 非正格評価の Java へのマッピング
○ Lazy インタフェースによる評価の遅延
○ Box クラスによるプリミティブ型の Lazy 化
○ Thunk クラスによる結果の使いまわし
Thunk You for Listening!
Presented by
チェシャ猫 (@y_taka_23)

More Related Content

What's hot

Java One 2012 Tokyo JVM Lang. BOF(Groovy)
Java One 2012 Tokyo JVM Lang. BOF(Groovy)Java One 2012 Tokyo JVM Lang. BOF(Groovy)
Java One 2012 Tokyo JVM Lang. BOF(Groovy)
Uehara Junji
 
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
koji lin
 
rpscala35-scala2.9.0
rpscala35-scala2.9.0rpscala35-scala2.9.0
rpscala35-scala2.9.0
Kenji Yoshida
 

What's hot (20)

はてなブックマーク in Scala
はてなブックマーク in Scalaはてなブックマーク in Scala
はてなブックマーク in Scala
 
LINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XMLLINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XML
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
Xtend - Javaの未来を今すぐ使う
Xtend - Javaの未来を今すぐ使うXtend - Javaの未来を今すぐ使う
Xtend - Javaの未来を今すぐ使う
 
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
 
Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016
 
Java One 2012 Tokyo JVM Lang. BOF(Groovy)
Java One 2012 Tokyo JVM Lang. BOF(Groovy)Java One 2012 Tokyo JVM Lang. BOF(Groovy)
Java One 2012 Tokyo JVM Lang. BOF(Groovy)
 
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
 
Scalaで型クラス入門
Scalaで型クラス入門Scalaで型クラス入門
Scalaで型クラス入門
 
Spectacular Future with clojure.spec
Spectacular Future with clojure.specSpectacular Future with clojure.spec
Spectacular Future with clojure.spec
 
怠惰なRubyistへの道 fukuoka rubykaigi01
怠惰なRubyistへの道 fukuoka rubykaigi01怠惰なRubyistへの道 fukuoka rubykaigi01
怠惰なRubyistへの道 fukuoka rubykaigi01
 
rpscala35-scala2.9.0
rpscala35-scala2.9.0rpscala35-scala2.9.0
rpscala35-scala2.9.0
 
Thinking in Cats
Thinking in CatsThinking in Cats
Thinking in Cats
 
C++ マルチスレッド 入門
C++ マルチスレッド 入門C++ マルチスレッド 入門
C++ マルチスレッド 入門
 
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーNode.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
 
コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門
 

Viewers also liked

Viewers also liked (10)

猫でもわかる! モデル検査器 SPIN 入門
猫でもわかる! モデル検査器 SPIN 入門猫でもわかる! モデル検査器 SPIN 入門
猫でもわかる! モデル検査器 SPIN 入門
 
Learn You a Frege for Great Good!
Learn You a Frege for Great Good!Learn You a Frege for Great Good!
Learn You a Frege for Great Good!
 
Fission で 始める Containerless Kubernetes #serverlesstokyo
Fission で 始める Containerless Kubernetes #serverlesstokyoFission で 始める Containerless Kubernetes #serverlesstokyo
Fission で 始める Containerless Kubernetes #serverlesstokyo
 
Hello, Type Systems! - Introduction to Featherweight Java
Hello, Type Systems! - Introduction to Featherweight JavaHello, Type Systems! - Introduction to Featherweight Java
Hello, Type Systems! - Introduction to Featherweight Java
 
AWS は形式手法の夢を見るか? - モデル検査器 Alloy によるインフラ設計
AWS は形式手法の夢を見るか? - モデル検査器 Alloy によるインフラ設計AWS は形式手法の夢を見るか? - モデル検査器 Alloy によるインフラ設計
AWS は形式手法の夢を見るか? - モデル検査器 Alloy によるインフラ設計
 
すごい Frege たのしく学ぼう!
すごい Frege たのしく学ぼう!すごい Frege たのしく学ぼう!
すごい Frege たのしく学ぼう!
 
机上の Kubernetes - 形式手法で見るコンテナオーケストレーション #NGK2016B
机上の Kubernetes -  形式手法で見るコンテナオーケストレーション #NGK2016B机上の Kubernetes -  形式手法で見るコンテナオーケストレーション #NGK2016B
机上の Kubernetes - 形式手法で見るコンテナオーケストレーション #NGK2016B
 
形式手法と AWS のおいしい関係。- モデル検査器 Alloy によるインフラ設計技法 #jawsfesta
形式手法と AWS のおいしい関係。- モデル検査器 Alloy によるインフラ設計技法 #jawsfesta形式手法と AWS のおいしい関係。- モデル検査器 Alloy によるインフラ設計技法 #jawsfesta
形式手法と AWS のおいしい関係。- モデル検査器 Alloy によるインフラ設計技法 #jawsfesta
 
形式手法で捗る!インフラ構成の設計と検証
形式手法で捗る!インフラ構成の設計と検証形式手法で捗る!インフラ構成の設計と検証
形式手法で捗る!インフラ構成の設計と検証
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
 

Similar to Frege, What a Non-strict Language

命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ
Naoki Kitora
 
Incanterの紹介
Incanterの紹介Incanterの紹介
Incanterの紹介
mozk_
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
Ra Zon
 

Similar to Frege, What a Non-strict Language (20)

たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ
 
これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツール
 
Incanterの紹介
Incanterの紹介Incanterの紹介
Incanterの紹介
 
JSX / Haxe / TypeScript
JSX / Haxe / TypeScriptJSX / Haxe / TypeScript
JSX / Haxe / TypeScript
 
Introduction to Categorical Programming (Revised)
Introduction to Categorical Programming (Revised)Introduction to Categorical Programming (Revised)
Introduction to Categorical Programming (Revised)
 
Scala 初心者が米田の補題を Scala で考えてみた
Scala 初心者が米田の補題を Scala で考えてみたScala 初心者が米田の補題を Scala で考えてみた
Scala 初心者が米田の補題を Scala で考えてみた
 
Introduction to Categorical Programming
Introduction to Categorical ProgrammingIntroduction to Categorical Programming
Introduction to Categorical Programming
 
Mesh tensorflow
Mesh tensorflowMesh tensorflow
Mesh tensorflow
 
NLPforml5
NLPforml5NLPforml5
NLPforml5
 
“Adoption and Focus: Practical Linear Types for Imperative Programming”他の紹介@P...
“Adoption and Focus: Practical Linear Types for Imperative Programming”他の紹介@P...“Adoption and Focus: Practical Linear Types for Imperative Programming”他の紹介@P...
“Adoption and Focus: Practical Linear Types for Imperative Programming”他の紹介@P...
 
Apache Spark チュートリアル
Apache Spark チュートリアルApache Spark チュートリアル
Apache Spark チュートリアル
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
[DL輪読会]Factorized Variational Autoencoders for Modeling Audience Reactions to...
[DL輪読会]Factorized Variational Autoencoders for Modeling Audience Reactions to...[DL輪読会]Factorized Variational Autoencoders for Modeling Audience Reactions to...
[DL輪読会]Factorized Variational Autoencoders for Modeling Audience Reactions to...
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!
 
Lispmeetup #53 PythonベースのLisp方言、 Hyのすすめ
Lispmeetup #53 PythonベースのLisp方言、 HyのすすめLispmeetup #53 PythonベースのLisp方言、 Hyのすすめ
Lispmeetup #53 PythonベースのLisp方言、 Hyのすすめ
 
Haskell勉強会 in ie
Haskell勉強会 in ieHaskell勉強会 in ie
Haskell勉強会 in ie
 
関数型プログラミング入門 for Matlab ユーザー
関数型プログラミング入門 for Matlab ユーザー関数型プログラミング入門 for Matlab ユーザー
関数型プログラミング入門 for Matlab ユーザー
 

Recently uploaded

Recently uploaded (7)

NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 

Frege, What a Non-strict Language

  • 1. Frege, What a Non-strict Language チェシャ猫 (@y_taka_23) NL 名古屋 (2016/04/16)
  • 2. 自己紹介 ● 名前 : チェシャ猫 ○ Twitter: @y_taka_23 ○ GitHub: y-taka-23 ● 好きなもの ○ Haskell ○ 形式手法 (Coq, Alloy, SPIN, etc...) ● 自称 Frege エバンジェリスト
  • 3. 本日の内容 ● JVM 言語 Frege の概要 ○ 基本的な特徴 ○ Haskell との比較 ● Java コード生成と非正格評価 ○ コンパイルの仕組み ○ 評価戦略のマッピング
  • 4. 1. JVM 言語 Frege の概要
  • 5. “Frege is a Haskell for JVM”
  • 6. Frege のエッセンス ● 純粋・非正格評価な関数型言語 ○ 本日のメイントピック ● 強い静的型付け ○ Hindley-Milner 型推論 + Rank-N types ● モナドによる Java の呼び出し ○ 歌舞伎座.tech #9 での発表スライド参照 ○ 「すごい Frege たのしく学ぼう!」で検索
  • 8. Hello, Frege module Hello where greeting :: String -> String greeting name = “Hello, “ ++ name main :: [String] -> IO () main args = do putStrLn $ greeting “World”
  • 9. Hello, Frege module Hello where greeting :: String -> String greeting name = “Hello, “ ++ name main :: [String] -> IO () main args = do putStrLn $ greeting “World”
  • 11. 『すごい Haskell』翻訳実験 ● 全サンプルコードを Frege に ○ https://github.com/y-taka-23/learn-you-a-frege ● だいたい丸写しでコンパイルが通る ○ 構文論的には Haskell 2010 互換
  • 13. Frege のコンパイル ● コンパイラ自身も Frege 実装 ● JVM 系ビルドツールが利用可 ○ Gradle, Maven, sbt. Leiningen, Bazel ● コンパイルすると Java ソースコードに ○ あくまでも中間生成コードで可読性低 ○ 最新版 v3.24 で生成ロジックが変更
  • 14. Hello again, Frege module Hello where greeting :: String -> String greeting name = “Hello, “ ++ name main :: [String] -> IO () main args = do putStrLn $ greeting “World”
  • 15. Hello again, Frege module Hello where greeting :: String -> String greeting name = “Hello, “ ++ name main :: [String] -> IO () main args = do putStrLn $ greeting “World”
  • 16. Hello again, Frege module Hello where greeting :: String -> String greeting name = “Hello, “ ++ name main :: [String] -> IO () main args = do putStrLn $ greeting “World” public static void main(String[] args) {...}
  • 17. Frege の型 = Java の型?
  • 18. Frege によるたらい回し関数 tarai :: Int -> Int -> Int -> Int tarai x y z = if x <= y then y else tarai (tarai (x - 1) y z) (tarai (y - 1) z x) (tarai (z - 1) x y)
  • 19. 予想される Java コード static int tarai(int x, int y, int z) { if (x <= y) { return y; } else { return tarai( tarai(x - 1, y, z), tarai(y - 1, z, x), tarai(z - 1, x, y)); } }
  • 21. 生成されるコードの骨子 static int tarai(int x, int y, Lazy<Integer> z) { if (x <= y) { return y; } else { return tarai( tarai(x - 1, y, z), tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)), Thunk.<Integer>shared( (Lazy<Integer>)(() -> tarai( (int)z.call() - 1, x, Thunk.<Integer>lazy(y)))) ); } }
  • 23. 評価戦略のマッピング ● Haskell の非正格評価を Java 上で再現 ● ここで関連する要素は主に 3 つ ○ frege.run8.Lazy<T> ○ frege.run8.Box<T> ○ frege.run8.Thunk<T>
  • 24. frege.run8.Lazy<T> ● Callable のサブインタフェース ○ call() メソッドで値を取得 ● R 型の式の評価を遅延させる ○ 役割は Supplier<R> に類似 ● Frege の代数的データ型や関数は デフォルトで Lazy の実装クラスに
  • 25. frege.run8.Lazy<T> static int tarai(int x, int y, Lazy<Integer> z) { if (x <= y) { return y; } else { return tarai( tarai(x - 1, y, z), tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)), Thunk.<Integer>shared( (Lazy<Integer>)(() -> tarai( (int)z.call() - 1, x, Thunk.<Integer>lazy(y)))) ); } }
  • 26. frege.run8.Lazy<T> static int tarai(int x, int y, Lazy<Integer> z) { if (x <= y) { return y; } else { return tarai( tarai(x - 1, y, z), tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)), Thunk.<Integer>shared( (Lazy<Integer>)(() -> tarai( (int)z.call() - 1, x, Thunk.<Integer>lazy(y)))) ); } }
  • 27. frege.run8.Box<T> ● Lazy の実装クラスその 1 ● Thunk.<T>lazy(x) で生成 ● Lazy になっていない型のラッパー ○ 役割は IntSupplier などと同様 ○ call() されるとラップされている値を返す
  • 28. frege.run8.Box<T> static int tarai(int x, int y, Lazy<Integer> z) { if (x <= y) { return y; } else { return tarai( tarai(x - 1, y, z), tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)), Thunk.<Integer>shared( (Lazy<Integer>)(() -> tarai( (int)z.call() - 1, x, Thunk.<Integer>lazy(y)))) ); } }
  • 29. frege.run8.Box<T> static int tarai(int x, int y, Lazy<Integer> z) { if (x <= y) { return y; } else { return tarai( tarai(x - 1, y, z), tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)), Thunk.<Integer>shared( (Lazy<Integer>)(() -> tarai( (int)z.call() - 1, x, Thunk.<Integer>lazy(y)))) ); } }
  • 30. frege.run8.Thunk<T> ● Lazy の実装クラスその 2 ● Thunk.<T>shared(x)で生成 ● Call-by-need を実現 ○ x が共有可能なら shared(x) は x を返す ○ 初めて call() されると内部に値を保持 ○ 次に call() された際にはその値を返す
  • 31. frege.run8.Thunk<T> static int tarai(int x, int y, Lazy<Integer> z) { if (x <= y) { return y; } else { return tarai( tarai(x - 1, y, z), tarai(y - 1, (int)z.call(), Thunk.<Integer>lazy(x)), Thunk.<Integer>shared( (Lazy<Integer>)(() -> tarai( (int)z.call() - 1, x, Thunk.<Integer>lazy(y)))) ); } }
  • 32. McCarthy による変種 tak :: Int -> Int -> Int -> Int tak x y z = if x <= y then z else tak (tak (x - 1) y z) (tak (y - 1) z x) (tak (z - 1) x y)
  • 33. McCarthy による変種 tak :: Int -> Int -> Int -> Int tak x y z = if x <= y then z else tak (tak (x - 1) y z) (tak (y - 1) z x) (tak (z - 1) x y)
  • 34. McCarthy 版から生成されるコード static int tak(int x, int y, int z) { if (x <= y) { return z; } else { return tak( tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y)); } }
  • 35. McCarthy 版から生成されるコード static int tak(int x, int y, int z) { if (x <= y) { return z; } else { return tak( tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y)); } }
  • 36. まとめ ● Frege は JVM のための Haskell ○ 構文は Haskell そのまま ○ JVM 系ビルドツールが使用可能 ● 非正格評価の Java へのマッピング ○ Lazy インタフェースによる評価の遅延 ○ Box クラスによるプリミティブ型の Lazy 化 ○ Thunk クラスによる結果の使いまわし
  • 37. Thunk You for Listening! Presented by チェシャ猫 (@y_taka_23)