Template Haskell のお勉強ちう、そのに ‐ runIO
Template Haskell のお勉強ちう - 日曜プログラマがダラダラ書く のつづきです。
github のリポジトリはこちら → https://github.com/h-hirai/SimpleRayTracer
結果的にすごい簡単になったというおはなし。
前回、あまり大きなリストリテラルを作ると、ghc が落ちるので、あまり大きな画像は (というか、かなり小さな画像しか) レンダリングできないというところで終わりました。
さて、前回もリンクしました @mr_konn さんによるチュートリアルによりますと、Q モナドの中では任意の IO 処理が実行できます。じゃぁ、もういっそファイル書き出しまでコンパイル中に実行しちゃえばいいような気がする……、と思って書いたコードが以下になります。
{-# LANGUAGE TemplateHaskell #-} module RayTracerTH where import Language.Haskell.TH import RayTracer import Vector3D import Codec.BMP runTrace :: World -> Vector3D -> Float -> Float -> Float -> Float -> Float -> ExpQ runTrace w eyePos startx endx starty endy step = do runIO $ writeBMP "result.bmp" $ trace w eyePos startx endx starty endy step tupE []
前回の RayTracerTH と違い、RayTracer.trace をそのまま使用する形になっています*1。というか、ほとんど通常版レイトレーサの main の内容が runIO の中に引っ越してきただけです。
呼び出し側になる main はこんなかんじ
{-# LANGUAGE TemplateHaskell #-} module Main where import RayTracerTH import RayTracer (world_b, world_c, eyePos) main :: IO () main = return $(runTrace (world_b ++ world_c) eyePos (-96) 96 (-54) 54 1.0)
これで、
$ ghc --make ray_tracer_th.hs
のようにビルドすると、実行ファイル ray_tracer_th と一緒に result.bmp ができます。通常板レイトレーサと同じ程度の出力サイズでも問題なくレンダリングでき、レンダリング (コンパイル) 時間も同程度になりました。*2
一方、ray_tracer_th を実行しても何も起こりません。上記の main は、接合後には
main :: IO () main = return ()
のようになっているはずです。
……というか、こんな main や実行ファイルは不要ですね。消してしまいましょう。runTrace もなくなって、RayTracerTH はこんなかんじになります*3。
{-# LANGUAGE TemplateHaskell #-} module RayTracerTH where import Language.Haskell.TH import Codec.BMP import RayTracer do runIO $ writeBMP "result.bmp" $ trace (world_b ++ world_c) eyePos (-96) 96 (-54) 54 1.0 return []
実行ファイルも作りませんので、このモジュールだけをただコンパイルして、result.bmp を作ります。*4
$ ghc --make RayTracerTH.hs
えー……、もはや runghc となにが違うのか。ここまでくると、処理が実行時に行われようが、コンパイル時に行われようが同じじゃん、という感じになってきます。ほんとにスクリプト言語のプログラムを実行してる気分。
と、このように、Template Hasekell によるコンパイル時レイトレーシングは、通常のレイトレーサに、ごく薄いラッパをかぶせるだけで実現できることが分かりました。
……ぶっちゃけ、これではネタ的にぜんぜん面白くありません。とりあえず、今後はコンパイル時とか言わずに、普通のレイトレーサとして気が済むまで改良してみようかな、とか思ってます。これといって特殊なお話にはならないと思うので、ここではこれのお話はここまで*5。
これとは別に、Quasi Quote を使ったしょーもないネタがあるので、うまくいったら、そのさん、はそれで。