IdrisでWebアプリを書く

13,504 views

Published on

IdrisでWebアプリを書く @天下一altJS武闘会

Published in: Technology

IdrisでWebアプリを書く

  1. 1. IdrisでWebアプリを書く 田中英行 @天下一altJS武闘会
  2. 2. 自己紹介 • 田中英行(@tanakh) • Haskellとかやってます • 「すごいHaskellたのしく学ぼう」翻訳 • 「Parallel and Concurrent Programming in Haskell」翻訳中 • Idris初心者
  3. 3. Idrisとは? • http://www.idris-lang.org/ • “Fully Dependent Type” なプログラミング言語 • Cf. CoqとかAgdaとかATSとか • 純粋関数型 • 正格評価 • 様々な言語へのバックエンド • C言語 • LLVM • Java • JavaScript
  4. 4. 処理系のインストール • $ cabal install idris $ idris ____ __ _ / _/___/ /____(_)____ / // __ / ___/ / ___/ Version 0.9.13 _/ // /_/ / / / (__ ) http://www.idris-lang.org/ /___/__,_/_/ /_/____/ Type :? for help Idris> █
  5. 5. 構文など • 大体Haskell! • 基本的な構文 • 型クラスなどなど • リスト・モナド内包 • モナド記法などなど
  6. 6. Dependent Type (依存型) • 値に依存した型 • 型のパラメータとして値が取れる • 型と値の区別があんまりない • 型に対して計算できる • ・・・ • 要するにめっちゃ強い型 • 証明とかにも使える
  7. 7. めっちゃ強い型で何するの? • 証明 • カリー・ハワード同型対応により、 「型の表現力=命題の表現力」 • CoqとかAgdaとかはこっちがメイン • 安全なプログラムを書く • 単純により多くのことを型レベルで保証したい • 例えば、配列のアクセスが範囲を超えないなど • システムプログラムとかによさそう • Idrisはこっちが目標っぽい
  8. 8. 例:長さを型に持つリスト data Vect : Nat -> Type -> Type where Nil : Vect Z a (::) : a -> Vect k a -> Vect (S k) a (++) : Vect n a -> Vect m a -> Vect (n + m) a (++) Nil ys = ys (++) (x :: xs) ys = x :: xs ++ ys index : Fin n -> Vect n a -> a index fZ (x :: xs) = x index (fS k) (x :: xs) = index k xs
  9. 9. 例:長さを型に持つリスト Idris> the (Vect _ _) $ [1,2,3] ++ [4,5,6] [1, 2, 3, 4, 5, 6] : Vect 6 Integer Idris> Vect.index 5 $ [1,2,3] ++ [4,5,6] 6 : Integer Idris> Vect.index 10 $ [1,2,3] ++ [4,5,6] (input):1:15:When elaborating argument prf to Prelude.Fin.fromInteger: Can't unify IsJust (Just x) with IsJust (integerToFin 10 (3 + 3))
  10. 10. DOM操作 • altJSの本懐、DOM操作 • iQuery • https://github.com/idris-hackers/iQuery • というのがあるのだが・・・
  11. 11. iQuery • ものすごく機能が足りてない • ラッパーが抽象型で生のJSオブジェクトにアク セスできない • → 使えない 完全に名前負け
  12. 12. というわけで • 1から作るしかない • ただのJavaScriptにコンパイルできる言語 • altJSとはなんだったのか・・・ • これだったらEmscriptenでC言語もaltJSなんでは
  13. 13. FFIでJavaScriptとやりとりする • 任意のJavaScriptコードを埋め込める • コードと引数は静的に検査される alert : String -> IO () alert msg = mkForeign (FFun "alert(%0)" [FString] msg
  14. 14. %include • JavaScriptのコードをincludeできる (生成されるJSの先頭にくっつくだけ) %include JavaScript "lib.js" twice : (Int -> Int) -> Int -> IO Int twice f x = mkForeign (FFun "twice(%0,%1)" [FFunction FInt FInt, FInt] FInt) f x main : IO () main = alert (show !(twice (+1) 1)) -- 3 がでる // lib.js function twice(f, x) { return f(f(x)); }
  15. 15. 適当なライブラリを作る Document : Type Document = Ptr document : Document document = unsafePerformIO $ mkForeign (FFun "document" [] set : Ptr -> String -> String -> IO () set e mem val = mkForeign (FFun "%0[%1]=%2" [FPtr, FString, FString] FUnit) e mem val get : Ptr -> String -> IO String get e mem = mkForeign (FFun "%0[%1]" [FPtr, FString] FString) e
  16. 16. 構文定義構文 • Idrisには構文を定義する構文がある! • 例:ifの定義 boolCase : (x:Bool) -> Lazy a -> Lazy a -> a boolCase True t e = t boolCase False t e = e syntax "if" [test] "then" [t] "else" [e] = boolCase test t e (´・_・`).oO(どういう仕組みなんだろう・・・)
  17. 17. 使用例 syntax [object] "[" [member] "]" ":=" [value] = set object member value syntax [object] "[" [member] "]" = get object member main : IO () main = do document["innerHTML"] := "(´・_・`)<つらぽよ"
  18. 18. TypeProvider • F#のTypeProviderみたいなのもあるんですってよ!
  19. 19. デモ • ライフゲーム • まるばつゲーム(負けないことの証明付き)
  20. 20. デモ • ライフゲーム • まるばつゲーム(負けないことの証明付き)
  21. 21. Idrisのいけてないところ • 添字アクセスO(1)の配列がない • メモリバッファの型はあるみたいなので、それの上 に自作すれば良いのだろうか • IORefがない • とりあえずはJavaScriptのFFIで作れば良いか・・・ • なんだかものすごい本末転倒感
  22. 22. Idrisのいけてないところ • 型検査が死ぬほど遅い • コードの長さに対して指数的に増えていく (ようにみえる) • 正直コードを保存する度に苦痛なレベル • コンパイルされたコードが遅い • せっかく正格評価なのに、クソ遅い • コード生成器の実装がクソ • CのバックエンドでHaskellの10倍ぐらい遅い • Unboxingとかインライニングとか特殊化とかたぶんこの 辺全く実装されていない
  23. 23. Idrisのいけてないところ • 並行ライブラリが標準ライブラリにあるが、 JavaScriptのランタイムでは未サポート _人人人人人人人人人人人_ > Not Yet Implemented <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
  24. 24. Idrisのいけてないところ • (僕は)証明が書けない • 例えば、リストの要素アクセス • Listは型に長さを含まない • アクセス時は、添字が長さよりも小さいという証明を与 える必要がある・・・ Idris> :doc List.index index : (n : Nat) -> (l : List a) -> (ok : lt n (length l) = -> a Find a particular element of a list. Arguments: ok : lt n (length l) = True -- a proof that the within bounds
  25. 25. beleave_me!! Idris> :doc believe_me believe_me : a -> b Subvert the type checker. This function is abstract, so it not reduce in the type checker. Use it with care - it can in segfaults or worse! Idris> :doc really_believe_me really_believe_me : a -> b Subvert the type checker. This function will reduce in th checker. Use it with extreme care - it can result in or worse!
  26. 26. まとめ • IdrisでWebアプリを書くのは時期尚早 • 可能性は感じる • 分野を開拓したい人にはおすすめ! • デファクトのWebフレームワークを作れるか も!?

×