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.

Frege, What a Non-strict Language

NL 名古屋の発表スライドです。Haskell ライクな JVM 言語 Frege を題材に、非正格な評価戦略を Java 上で実現する方法について解説します。なお、スライド中に登場するサンプルコードの詳細は、ブログ記事 http://ccvanishing.hateblo.jp/entry/2016/04/17/201842 を参照のこと。

  • Login to see the comments

Frege, What a Non-strict Language

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

×