More Related Content Similar to Frege, What a Non-strict Language (20) Frege, What a Non-strict Language2. 自己紹介
● 名前 : チェシャ猫
○ Twitter: @y_taka_23
○ GitHub: y-taka-23
● 好きなもの
○ Haskell
○ 形式手法 (Coq, Alloy, SPIN, etc...)
● 自称 Frege エバンジェリスト
3. 本日の内容
● JVM 言語 Frege の概要
○ 基本的な特徴
○ Haskell との比較
● Java コード生成と非正格評価
○ コンパイルの仕組み
○ 評価戦略のマッピング
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”
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) {...}
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))))
);
}
}
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))))
);
}
}
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))))
);
}
}
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 クラスによる結果の使いまわし