1 -- | The Cardinal module contains the Cardinal data type, representing
2 -- a cardinal direction (one of the 26 directions surrounding the
3 -- center of a cube. In addition to those 26 directions, we also
4 -- include the interior point and a number of composite types that
5 -- allow us to perform arithmetic on directions.
9 import Control.Monad (liftM, liftM2)
10 import Prelude hiding (LT)
11 import Test.QuickCheck (Arbitrary(..), oneof)
13 data Cardinal = F -- ^ Front
31 | FLD -- ^ Front Left Down
32 | FLT -- ^ Front Left Top
33 | FRD -- ^ Front Right Down
34 | FRT -- ^ Front Right Top
35 | BLD -- ^ Back Left Down
36 | BLT -- ^ Back Left Top
37 | BRD -- ^ Back Right Down
38 | BRT -- ^ Back Right Top
40 | Scalar Double -- ^ A wrapper around a scalar value.
41 | Sum Cardinal Cardinal -- ^ The sum of two directions.
42 | Difference Cardinal Cardinal
43 -- ^ The difference of two directions, the first minus the second.
44 | Product Cardinal Cardinal -- ^ The product of two directions.
45 | Quotient Cardinal Cardinal
46 -- ^ The quotient of two directions, the first divided by the
51 -- | By making Cardinal an instance of 'Num', we gain the ability to
52 -- add, subtract, and multiply directions. The results of these
53 -- operations are never actually calculated; the types just keep
54 -- track of which operations were performed in which order.
55 instance Num Cardinal where
57 x - y = Difference x y
59 negate = Product (Scalar (-1))
62 fromInteger x = Scalar (fromIntegral x)
65 -- | Like the Num instance, the 'Fractional' instance allows us to
66 -- take quotients of directions.
67 instance Fractional Cardinal where
69 recip = Quotient (Scalar 1)
70 fromRational x = Scalar (fromRational x)
74 instance Arbitrary Cardinal where
75 arbitrary = oneof [f,b,l,r,d,t,fl,fr,fd,ft,bl,br,bd,bt,ld,lt,
76 rd,rt,fld,flt,frd,frt,bld,blt,brd,brt,i,
77 scalar,csum,cdiff,cprod,cquot]
106 scalar = liftM Scalar arbitrary
107 csum = liftM2 Sum arbitrary arbitrary
108 cdiff = liftM2 Difference arbitrary arbitrary
109 cprod = liftM2 Product arbitrary arbitrary
110 cquot = liftM2 Quotient arbitrary arbitrary
113 -- | Rotate a cardinal direction counter-clockwise about the x-axis.
114 ccwx :: Cardinal -> Cardinal
142 ccwx (Scalar s) = (Scalar s)
143 ccwx (Sum c0 c1) = Sum (ccwx c0) (ccwx c1)
144 ccwx (Difference c0 c1) = Difference (ccwx c0) (ccwx c1)
145 ccwx (Product c0 c1) = Product (ccwx c0) (ccwx c1)
146 ccwx (Quotient c0 c1) = Quotient (ccwx c0) (ccwx c1)
148 -- | Rotate a cardinal direction clockwise about the x-axis.
149 cwx :: Cardinal -> Cardinal
150 cwx = ccwx . ccwx . ccwx
153 -- | Rotate a cardinal direction counter-clockwise about the y-axis.
154 ccwy :: Cardinal -> Cardinal
182 ccwy (Scalar s) = (Scalar s)
183 ccwy (Sum c0 c1) = Sum (ccwy c0) (ccwy c1)
184 ccwy (Difference c0 c1) = Difference (ccwy c0) (ccwy c1)
185 ccwy (Product c0 c1) = Product (ccwy c0) (ccwy c1)
186 ccwy (Quotient c0 c1) = Quotient (ccwy c0) (ccwy c1)
188 -- | Rotate a cardinal direction clockwise about the y-axis.
189 cwy :: Cardinal -> Cardinal
190 cwy = ccwy . ccwy . ccwy
193 -- | Rotate a cardinal direction counter-clockwise about the z-axis.
194 ccwz :: Cardinal -> Cardinal
222 ccwz (Scalar s) = (Scalar s)
223 ccwz (Sum c0 c1) = Sum (ccwz c0) (ccwz c1)
224 ccwz (Difference c0 c1) = Difference (ccwz c0) (ccwz c1)
225 ccwz (Product c0 c1) = Product (ccwz c0) (ccwz c1)
226 ccwz (Quotient c0 c1) = Quotient (ccwz c0) (ccwz c1)
228 -- | Rotate a cardinal direction clockwise about the z-axis.
229 cwz :: Cardinal -> Cardinal
230 cwz = ccwz . ccwz . ccwz