frege, what a non-strict language

37
Frege, What a Non-strict Language チェシャ猫 (@y_taka_23) NL 名古屋 (2016/04/16)

Upload: ytaka23

Post on 16-Apr-2017

1.901 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Frege, What a Non-strict Language

Frege,What a Non-strict Language

チェシャ猫 (@y_taka_23)NL 名古屋 (2016/04/16)

Page 2: Frege, What a Non-strict Language

自己紹介

● 名前 : チェシャ猫

○ Twitter: @y_taka_23

○ GitHub: y-taka-23

● 好きなもの

○ Haskell

○ 形式手法 (Coq, Alloy, SPIN, etc...)

● 自称 Frege エバンジェリスト

Page 3: Frege, What a Non-strict Language

本日の内容

● JVM 言語 Frege の概要

○ 基本的な特徴

○ Haskell との比較

● Java コード生成と非正格評価

○ コンパイルの仕組み

○ 評価戦略のマッピング

Page 4: Frege, What a Non-strict Language

1. JVM 言語 Frege の概要

Page 5: Frege, What a Non-strict Language

“Frege is a Haskell for JVM”

Page 6: Frege, What a Non-strict Language

Frege のエッセンス

● 純粋・非正格評価な関数型言語

○ 本日のメイントピック

● 強い静的型付け

○ Hindley-Milner 型推論 + Rank-N types

● モナドによる Java の呼び出し

○ 歌舞伎座.tech #9 での発表スライド参照

○ 「すごい Frege たのしく学ぼう!」で検索

Page 7: Frege, What a Non-strict Language

Q: どんな文法?

Page 8: Frege, What a Non-strict Language

Hello, Frege

module Hello where

greeting :: String -> Stringgreeting name = “Hello, “ ++ name

main :: [String] -> IO ()main args = do putStrLn $ greeting “World”

Page 9: Frege, What a Non-strict Language

Hello, Frege

module Hello where

greeting :: String -> Stringgreeting name = “Hello, “ ++ name

main :: [String] -> IO ()main args = do putStrLn $ greeting “World”

Page 10: Frege, What a Non-strict Language

A: ほぼ Haskell

Page 11: Frege, What a Non-strict Language

『すごい Haskell』翻訳実験

● 全サンプルコードを Frege に○ https://github.com/y-taka-23/learn-you-a-frege

● だいたい丸写しでコンパイルが通る

○ 構文論的には Haskell 2010 互換

Page 12: Frege, What a Non-strict Language

2. Java コード生成と非正格評価

Page 13: Frege, What a Non-strict Language

Frege のコンパイル

● コンパイラ自身も Frege 実装

● JVM 系ビルドツールが利用可

○ Gradle, Maven, sbt. Leiningen, Bazel

● コンパイルすると Java ソースコードに

○ あくまでも中間生成コードで可読性低

○ 最新版 v3.24 で生成ロジックが変更

Page 14: Frege, What a Non-strict Language

Hello again, Frege

module Hello where

greeting :: String -> Stringgreeting name = “Hello, “ ++ name

main :: [String] -> IO ()main args = do putStrLn $ greeting “World”

Page 15: Frege, What a Non-strict Language

Hello again, Frege

module Hello where

greeting :: String -> Stringgreeting name = “Hello, “ ++ name

main :: [String] -> IO ()main args = do putStrLn $ greeting “World”

Page 16: Frege, What a Non-strict Language

Hello again, Frege

module Hello where

greeting :: String -> Stringgreeting name = “Hello, “ ++ name

main :: [String] -> IO ()main args = do putStrLn $ greeting “World”

public static void main(String[] args) {...}

Page 17: Frege, What a Non-strict Language

Frege の型 = Java の型?

Page 18: Frege, What a Non-strict Language

Frege によるたらい回し関数

tarai :: Int -> Int -> Int -> Inttarai 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)

Page 19: Frege, What a Non-strict Language

予想される 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)); }}

Page 20: Frege, What a Non-strict Language

コンパイルしてみる

Page 21: Frege, What a Non-strict Language

生成されるコードの骨子

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)))) ); }}

Page 22: Frege, What a Non-strict Language

意外と複雑だった

Page 23: Frege, What a Non-strict Language

評価戦略のマッピング

● Haskell の非正格評価を Java 上で再現

● ここで関連する要素は主に 3 つ

○ frege.run8.Lazy<T>

○ frege.run8.Box<T>

○ frege.run8.Thunk<T>

Page 24: Frege, What a Non-strict Language

frege.run8.Lazy<T>

● Callable のサブインタフェース

○ call() メソッドで値を取得

● R 型の式の評価を遅延させる

○ 役割は Supplier<R> に類似

● Frege の代数的データ型や関数は

デフォルトで Lazy の実装クラスに

Page 25: Frege, What a Non-strict Language

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)))) ); }}

Page 26: Frege, What a Non-strict Language

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)))) ); }}

Page 27: Frege, What a Non-strict Language

frege.run8.Box<T>

● Lazy の実装クラスその 1

● Thunk.<T>lazy(x) で生成

● Lazy になっていない型のラッパー

○ 役割は IntSupplier などと同様

○ call() されるとラップされている値を返す

Page 28: Frege, What a Non-strict Language

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)))) ); }}

Page 29: Frege, What a Non-strict Language

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)))) ); }}

Page 30: Frege, What a Non-strict Language

frege.run8.Thunk<T>

● Lazy の実装クラスその 2

● Thunk.<T>shared(x)で生成

● Call-by-need を実現

○ x が共有可能なら shared(x) は x を返す

○ 初めて call() されると内部に値を保持

○ 次に call() された際にはその値を返す

Page 31: Frege, What a Non-strict Language

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)))) ); }}

Page 32: Frege, What a Non-strict Language

McCarthy による変種

tak :: Int -> Int -> Int -> Inttak 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)

Page 33: Frege, What a Non-strict Language

McCarthy による変種

tak :: Int -> Int -> Int -> Inttak 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)

Page 34: Frege, What a Non-strict Language

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)); }}

Page 35: Frege, What a Non-strict Language

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)); }}

Page 36: Frege, What a Non-strict Language

まとめ

● Frege は JVM のための Haskell○ 構文は Haskell そのまま

○ JVM 系ビルドツールが使用可能

● 非正格評価の Java へのマッピング

○ Lazy インタフェースによる評価の遅延

○ Box クラスによるプリミティブ型の Lazy 化

○ Thunk クラスによる結果の使いまわし

Page 37: Frege, What a Non-strict Language

Thunk You for Listening!Presented by

チェシャ猫 (@y_taka_23)