Upload
ytaka23
View
3.605
Download
0
Embed Size (px)
Citation preview
すごい Frege たのしく学ぼう!
Learn You a Frege for Great Good!
チェシャ猫 (@y_taka_23)
歌舞伎座.tech #9 (2016/03/20)
自己紹介
● 名前 : チェシャ猫
○ Twitter: @y_taka_23
○ GitHub: y-taka-23
● 好きなもの
○ Haskell
○ 形式手法 (Coq, Alloy, SPIN etc...)
● 自称 Frege エバンジェリスト
“Frege is a Haskell for JVM”
本日の内容
● Frege とはどんな言語なのか?
○ 基本的な特徴
○ Haskell との比較
● JVM 言語としての Frege○ 非純粋性の取り扱い
○ Java ライブラリの呼び出し
1. Frege とはどんな言語なのか?
Frege のエッセンス
● 純粋・非正格評価な関数型言語
● 強い静的型付けと Hindley-Milner 型推論
● エレガントな Java の呼び出しが可能
Haskell による Hello, World
module Hello where
greeting :: String -> Stringgreeting name = “Hello, ” ++ name
main :: IO ()main = do putStrLn $ greeting “World”
Frege による Hello, World
module Hello where
greeting :: String -> Stringgreeting name = “Hello, ” ++ name
main :: [String] -> IO ()main args = do putStrLn $ greeting “World”
ほとんど一緒!
『すごい Haskell』翻訳実験
● 全サンプルコードを Frege に○ https://github.com/y-taka-23/learn-you-a-frege
● だいたい丸写しでコンパイルが通る
Haskell との互換性
● 文法、標準ライブラリはほぼ完全に互換
● ただし実用上の機能が使えない
○ 外部ライブラリ
○ 大部分の GHC 拡張
○ Template Haskell
● Java ライブラリの呼び出しが鍵
2. JVM 言語としての Frege
JVM 言語としてのアドバンテージ
● プラットフォーム非依存
○ コンパイルすると Java ソースコードに
● 既存の Java ライブラリが呼び放題
○ しかし副作用に関するスタンスが異なる
■ Frege : 純粋
■ Java : 非純粋、オブジェクトが状態を持つ
Frege の純粋性を保ちつつ
うまいこと Java を呼びたい
Java の非純粋性の 3 つのレベル
● イミュータブル
○ ???
● ミュータブルだが入出力なし
○ ???
● 入出力あり
○ ???
Java の非純粋性の 3 つのレベル
● イミュータブル
○ そのまま Frege のデータ型になる
● ミュータブルだが入出力なし
○ ???
● 入出力あり
○ ???
イミュータブルなクラス
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
イミュータブルなクラス
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
Frege で使う際の型名
イミュータブルなクラス
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
イミュータブルなら pure native
イミュータブルなクラス
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
Java での完全修飾クラス名
イミュータブルなクラス
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
コンストラクタは new
イミュータブルなクラス
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
Java の BigInteger#add
イミュータブルなクラス
data JBigInt = pure native java.math.BigInteger where pure native new :: String -> JBigInt pure native add :: JBigInt -> JBigInt -> JBigInt
add3 :: JBigInt -> JBigInt -> JBigInt -> JBigIntadd3 n1 n2 n3 = (n1.add n2).add n3
ドットでメソッド呼び出し
Java の非純粋性の 3 つのレベル
● イミュータブル
○ そのまま Frege のデータ型になる
● ミュータブルだが入出力なし
○ ???
● 入出力あり
○ IO モナドになる
入出力を伴うクラス
data JFReader = mutable native java.io.FileReader where native new :: String -> IO JFReader native read :: JFReader -> IO Int
readOneFrom :: String -> IO IntreadOneFrom filename = do fr <- JFReader.new filename fr.read
入出力を伴うクラス
data JFReader = mutable native java.io.FileReader where native new :: String -> IO JFReader native read :: JFReader -> IO Int
readOneFrom :: String -> IO IntreadOneFrom filename = do fr <- JFReader.new filename fr.read
入出力用なら mutable native
入出力を伴うクラス
data JFReader = mutable native java.io.FileReader where native new :: String -> IO JFReader native read :: JFReader -> IO Int
readOneFrom :: String -> IO IntreadOneFrom filename = do fr <- JFReader.new filename fr.read
戻り値は IO モナド
入出力を伴うクラス
data JFReader = mutable native java.io.FileReader where native new :: String -> IO JFReader native read :: JFReader -> IO Int
readOneFrom :: String -> IO IntreadOneFrom filename = do fr <- JFReader.new filename fr.read
IO モナドとして使用
Java の非純粋性の 3 つのレベル
● イミュータブル
○ そのまま Frege のデータ型になる
● ミュータブルだが入出力なし
○ ???
● 入出力あり
○ IO モナドになる
「表向き純粋」なメソッド
public String greeting(String name) { StringBuilder sb = new StringBuilder(“Hello, ”); sb.append(name); return sb.toString();}
「表向き純粋」なメソッド
public String greeting(String name) { StringBuilder sb = new StringBuilder(“Hello, ”); sb.append(name); return sb.toString();}
インスタンスの破壊的更新
「表向き純粋」なメソッド
public String greeting(String name) { StringBuilder sb = new StringBuilder(“Hello, ”); sb.append(name); return sb.toString();}
ただし引数と戻り値の関係は一定
ST モナドを使おう!
Java の非純粋性の 3 つのレベル
● イミュータブル
○ そのまま Frege のデータ型になる
● ミュータブルだが入出力なし
○ ST モナドになる
● 入出力あり
○ IO モナドになる
ST (State Transformer) モナド
● 破壊的更新を局所化できる
● ST s TypeName
○ s は「観測不可能」な内部状態
○ s は常に型変数で、アクセスできない
● 純粋な値を取り出せる
○ IO モナドでは取り出せない
ミュータブルなクラス
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
ミュータブルなクラス
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
入出力なしなら native のみ
ミュータブルなクラス
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
直接アクセス不可能な「状態」
ミュータブルなクラス
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
Mutable s でラップ
ミュータブルなクラス
data JBuilder = native java.lang.StringBuilder where native new :: String -> ST s (Mutable s JBuilder) native append :: Mutable s JBuilder -> String -> ST s (Mutable s JBuilder)
戻り値は ST モナド
ミュータブルなクラス
greeting :: String -> ST s Stringgreeting name = do sb <- JBuilder.new “Hello, ” sb.append name sb.toString
pureFunc :: String -> StringpureFunc name = (greeting name).run
ミュータブルなクラス
greeting :: String -> ST s Stringgreeting name = do sb <- JBuilder.new “Hello, ” sb.append name sb.toString
pureFunc :: String -> StringpureFunc name = (greeting name).run
ST モナドとして使用
ミュータブルなクラス
greeting :: String -> ST s Stringgreeting name = do sb <- JBuilder.new “Hello, ” sb.append name sb.toString
pureFunc :: String -> StringpureFunc name = (greeting name).run
run で純粋な値を取り出す
ミュータブルなクラス
greeting :: String -> ST s Stringgreeting name = do sb <- JBuilder.new “Hello, ” sb.append name sb.toString
pureFunc :: String -> StringpureFunc name = (greeting name).run
純粋関数の中で使用可能
まとめ
● Frege はまさに JVM のための Haskell○ 文法は Haskell そのまま
○ 学習コストはほぼゼロ
● エレガントな Java 呼び出し
○ Haskell 的な型システムと両立
○ pure, ST, IO の 3 段階で副作用の強さを表現