Agda2で遊んでみた

Haskell風構文のDependently Typed Programming LanguageであるAgda2を少し学んでみました。

インストールとか

ubuntu intrepidで使う場合、依存ライブラリのうち、zlibとQuickCheckだけは別途makeして入れる必要がありました。あとはdebパッケージですみました。

Adga2のソースをdarcsでとってきて中のREADMEにあるとおりにやれば、ビルドできます。zlibとQuickCheckは/usr/localにinstallで入れました。

ソースコードのファイル名は大文字始まりで、拡張子はagda

対話環境での実行はIオプションをつけます:

runghc Agda2/src/main/Main.hs -I MySample.agda

対話環境

プロンプトに「:?」でコマンド一覧が出るようです。:typeOfくらいしか使えませんでした。

ビルトインの利用

やり方

例:Hello.agda

module Hello where
{-# IMPORT System.IO.Unsafe #-}
data Unit : Set where
  unit : Unit
{-# COMPILED_DATA Unit () () #-}

data List (A : Set) : Set where
  nil : List A
  cons : A -> List A -> List A
{-# COMPILED_DATA List [] [] (:) #-}
{-# BUILTIN LIST List #-}
{-# BUILTIN NIL nil #-}

postulate
  String : Set
  IO : Set -> Set
  putStrLn  : String -> IO Unit
  unsafePerformIO : {A : Set} -> IO A -> A
  _>>=_ : {A B : Set} -> IO A -> (A -> IO B) -> IO B
  return : {A : Set} -> A -> IO A
{-# COMPILED_TYPE String String #-}
{-# BUILTIN STRING String #-}
{-# COMPILED_TYPE IO IO #-}
{-# BUILTIN IO IO #-}
{-# COMPILED putStrLn putStrLn #-}
{-# COMPILED unsafePerformIO (\_ -> unsafePerformIO) #-}
{-# COMPILED _>>=_ (\_ _ -> (>>=) :: IO a -> (a -> IO b) -> IO b) #-}
{-# COMPILED return (\_ -> return :: a -> IO a) #-}

main : IO Unit
main = putStrLn "Hello"

postulateは仮説のこと、この構文によって本体不要の型を定義できます。これらをCOMPILEDプラグマによってバックエンドのHaskellのオブジェクトに結びつけることになります。
読み込むコード中にでも埋めておけば、このプラグマBUILTINによって"abc"のようなリテラルが使えるようになります。

コード全体が正しく記述されていれば、cオプションでHaskellコードにコンパイルでき、mainを実行することができます。

$ runhaskell Agda2/src/main/Main.hs -c Hello.agda
$ ./MAlonzo/Hello
Hello

中途生成されるHello.hsものこるので、プラグマの仕組みはなんとなくわかるかも。

プラグマCOMPILED内のHaskellコード部(最右部分)は、現状そのまま生成コード内に埋め込まれるようで、型判定ミスだけでなく構文ミスでもghcコンパイルエラーとして表示されます。


とりあえず、ここまで。本題に入るまでが大変だったりするのは、こういうものにはよくあることですが。dependently typed progammingについては明日以降で。