IdrisでWebアプリを書く
田中英行
@天下一altJS武闘会
自己紹介
• 田中英行(@tanakh)
• Haskellとかやってます
• 「すごいHaskellたのしく学ぼう」翻訳
• 「Parallel and Concurrent Programming in
Haskell」翻訳中
• Idris初心者
Idrisとは?
• http://www.idris-lang.org/
• “Fully Dependent Type” なプログラミング言語
• Cf. CoqとかAgdaとかATSとか
• 純粋関数型
• 正格評価
• 様々な言語へのバックエンド
• C言語
• LLVM
• Java
• JavaScript
処理系のインストール
• $ cabal install idris
$ idris
____ __ _
/ _/___/ /____(_)____
/ // __ / ___/ / ___/ Version 0.9.13
_/ // /_/ / / / (__ ) http://www.idris-lang.org/
/___/__,_/_/ /_/____/ Type :? for help
Idris> █
構文など
• 大体Haskell!
• 基本的な構文
• 型クラスなどなど
• リスト・モナド内包
• モナド記法などなど
Dependent Type (依存型)
• 値に依存した型
• 型のパラメータとして値が取れる
• 型と値の区別があんまりない
• 型に対して計算できる
• ・・・
• 要するにめっちゃ強い型
• 証明とかにも使える
めっちゃ強い型で何するの?
• 証明
• カリー・ハワード同型対応により、
「型の表現力=命題の表現力」
• CoqとかAgdaとかはこっちがメイン
• 安全なプログラムを書く
• 単純により多くのことを型レベルで保証したい
• 例えば、配列のアクセスが範囲を超えないなど
• システムプログラムとかによさそう
• Idrisはこっちが目標っぽい
例:長さを型に持つリスト
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
例:長さを型に持つリスト
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))
DOM操作
• altJSの本懐、DOM操作
• iQuery
• https://github.com/idris-hackers/iQuery
• というのがあるのだが・・・
iQuery
• ものすごく機能が足りてない
• ラッパーが抽象型で生のJSオブジェクトにアク
セスできない
• → 使えない
完全に名前負け
というわけで
• 1から作るしかない
• ただのJavaScriptにコンパイルできる言語
• altJSとはなんだったのか・・・
• これだったらEmscriptenでC言語もaltJSなんでは
FFIでJavaScriptとやりとりする
• 任意のJavaScriptコードを埋め込める
• コードと引数は静的に検査される
alert : String -> IO ()
alert msg =
mkForeign (FFun "alert(%0)" [FString]
msg
%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)); }
適当なライブラリを作る
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
構文定義構文
• 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(どういう仕組みなんだろう・・・)
使用例
syntax [object] "[" [member] "]" ":=" [value] =
set object member value
syntax [object] "[" [member] "]" =
get object member
main : IO ()
main = do
document["innerHTML"] := "(´・_・`)<つらぽよ"
TypeProvider
• F#のTypeProviderみたいなのもあるんですってよ!
デモ
• ライフゲーム
• まるばつゲーム(負けないことの証明付き)
デモ
• ライフゲーム
• まるばつゲーム(負けないことの証明付き)
Idrisのいけてないところ
• 添字アクセスO(1)の配列がない
• メモリバッファの型はあるみたいなので、それの上
に自作すれば良いのだろうか
• IORefがない
• とりあえずはJavaScriptのFFIで作れば良いか・・・
• なんだかものすごい本末転倒感
Idrisのいけてないところ
• 型検査が死ぬほど遅い
• コードの長さに対して指数的に増えていく
(ようにみえる)
• 正直コードを保存する度に苦痛なレベル
• コンパイルされたコードが遅い
• せっかく正格評価なのに、クソ遅い
• コード生成器の実装がクソ
• CのバックエンドでHaskellの10倍ぐらい遅い
• Unboxingとかインライニングとか特殊化とかたぶんこの
辺全く実装されていない
Idrisのいけてないところ
• 並行ライブラリが標準ライブラリにあるが、
JavaScriptのランタイムでは未サポート
_人人人人人人人人人人人_
> Not Yet Implemented
<
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
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
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!
まとめ
• IdrisでWebアプリを書くのは時期尚早
• 可能性は感じる
• 分野を開拓したい人にはおすすめ!
• デファクトのWebフレームワークを作れるか
も!?

IdrisでWebアプリを書く