Haskellでレンダラーを書いてみるテスト #01: ベクトル型定義
いきなりここで詰まる。
追記:ここのHaskellレイトレ比較記事によるとtuple使うのはよくないらしい。後で参考にして書き直す。(ソースレポジトリが落ちてるぽい)
最初の案
-- Vector3.hs -- 3D Vector type definitions module Vector3 where type REAL = Double data Vector3 = Vector3 (REAL, REAL, REAL) deriving (Eq, Show, Read) instance Num Vector3 where Vector3 (xa, ya, za) + Vector3 (xb, yb, zb) = Vector3(xa + xb, ya + yb, za + zb)
ここで問題になるのは、+演算子。これを定義するためにNumクラスのインスタンスとしてしまうと、他に*演算子、abs, sigNum, fromInteger等の関数定義が必須になってしまう。
2番目の案
-- Vector3.hs -- 3D Vector type definitions module Vector3 ( REAL, Vector3, vadd, vsub, vdotp, vcrossp ) where type REAL = Double type Vector3 = (Double, Double, Double) vadd :: Vector3 -> Vector3 -> Vector3 (xa, ya, za) `vadd` (xb, yb, zb) = (xa + xb, ya + yb, za + zb) vsub :: Vector3 -> Vector3 -> Vector3 (xa, ya, za) `vsub` (xb, yb, zb) = (xa - xb, ya - yb, za - zb) vdotp :: Vector3 -> Vector3 -> REAL (xa, ya, za) `vdotp` (xb, yb, zb) = xa*xb + ya*yb + za*zb vcrossp :: Vector3 -> Vector3 -> Vector3 (xa, ya, za) `vcrossp` (xb, yb, zb) = (ya*zb - za*yb, za*xb - xa*zb, xa*yb - ya*xb)
こんなかんじ。
ユニットテスト
ユニットテストを書くのにはまっているのでHaskellでもそんな感じでいくことにする。
軽くググって、HUnitをつかってみることに。ghcに標準添付されている?のかghc-pkgによると既にインストール済みのようだ。
-- Vector3Test.hs : Vector3 module test import Vector3 import Test.HUnit testvadd = TestCase $ assertEqual "testing (1, 2, 3) + (3, 2, 1)" (4, 4, 4) ((1, 2, 3) `vadd` (3, 2, 1)) testvsub = TestCase $ assertEqual "testing (1, 2, 3) - (3, 2, 1)" (-2, 0, 2) ((1, 2, 3) `vsub` (3, 2, 1)) testvdotp = TestCase $ assertEqual "testing (1, 2, 3) dotp (3, 2, 1)" 10 ((1, 2, 3) `vdotp` (3, 2, 1)) testvcrossp = TestCase $ assertEqual "testing (1, 2, 3) crossp (4, 5, 6)" (-3, 6, -3) ((1, 2, 3) `vcrossp` (4, 5, 6)) main = runTestTT $ TestList [testvadd, testvsub, testvdotp, testvcrossp]
実行結果:
kouhei@snowshoe:~/svnwork/nyatr/trunk$ ghci Vector3Test.hs GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. [1 of 2] Compiling Vector3 ( Vector3.hs, interpreted ) [2 of 2] Compiling Main ( Vector3Test.hs, interpreted ) Ok, modules loaded: Main, Vector3. *Main> main Loading package HUnit-1.2.0.0 ... linking ... done. Cases: 4 Tried: 4 Errors: 0 Failures: 0 Counts {cases = 4, tried = 4, errors = 0, failures = 0
とりあえず今日はこんなところで。
ここまでのソースコード:http://websvn.nyaxtstep.com/viewvc.cgi/nyatr/trunk/?pathrev=622