The is going to be some of the most used code and it’s going to be a hot spot for bugs. A nice thing that Haskell does is make it very easy to define your own infix operators this should help a lot to keep things readable. Here’s the code:
module Vector (Vec3f, Color, (<+>), (<->), (<*>), (</>), (<.>), x, len, normed, Ray(Ray), at) where --general purpose 3 field vector type Vec3 a = (a, a, a) (<+>) :: (Num a) => Vec3 a -> Vec3 a -> Vec3 a (<+>) (x1,y1,z1) (x2,y2,z2) = (x1 + x2, y1 + y2, z1 + z2) (<->) :: (Num a) => Vec3 a -> Vec3 a -> Vec3 a (<->) (x1,y1,z1) (x2,y2,z2) = (x1 - x2, y1 - y2, z1 - z2) (<*>) :: (Num a) => a -> Vec3 a -> Vec3 a (<*>) r (x,y,z) = (r * x, r * y, r * z) (</>) :: (Fractional a) => Vec3 a -> a -> Vec3 a (</>) (x,y,z) r = (x / r, y / r, z / r) (<.>) :: (Num a) => Vec3 a -> Vec3 a -> a (<.>) (x1,y1,z1) (x2,y2,z2) = (x1 * x2) + (y1 * y2) + (z1 * z2) --cross product x :: (Num a) => Vec3 a -> Vec3 a -> Vec3 a x (x1,y1,z1) (x2,y2,z2) = ((y1 * z2 - y2 * z1), (x1*z2 - x2*z1), (x1 * y2 - y1 * x2)) len :: (Floating a) => Vec3 a -> a len v = sqrt (v <.> v) normed :: (Floating a) => Vec3 a -> Vec3 a normed v = v </> len v type Vec3f = (Vec3 Float) type Color = (Vec3 Int) --Rays data Ray = Ray {orig :: Vec3f, dir :: Vec3f } deriving (Show) at::Ray -> Float -> Vec3 Float at (Ray orig dir) t = orig <+> (t <*> dir) |
Pretty basic so far, but this should be enough to get me started. Haskell wasn’t happy when I tried to make the infix operators without the “<>“s so I guess I’m stuck with them (unless someone can tell me how to fix it.) However this does still look pretty nice:
*Vector> (1,1,1) <+> (5,5,5) (6,6,6) *Vector> (1,1,1) <-> (5,5,5) (-4,-4,-4) *Vector> 5 <*> (1,2,3) (5,10,15) *Vector> (1,2,3) </> 5 (0.2,0.4,0.6) *Vector> (1,2,3) <.> (3,2,1) 10 *Vector> (1,0,0) `x` (0,1,0) (0,0,1) *Vector> len (1,1,0) 1.4142135623730951 *Vector> sqrt 2 1.4142135623730951 *Vector> normed (1,2,3) (0.2672612419124244,0.5345224838248488,0.8017837257372732) *Vector> len (normed (1,2,3)) 1.0 *Vector> (Ray (0,0,0) (4,3,2)) `at` 100 (400.0,300.0,200.0) |