{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE StandaloneDeriving #-}
import Data.List (nub, sort)
class (Enum a, Bounded a) => BoundedEnum a where
range :: [a]
range = enumFrom minBound
class (Eq a, Enum a, Bounded a) => CyclicEnum a where
cpred :: a -> a
cpred d
| d == minBound = maxBound
| otherwise = pred d
csucc :: a -> a
csucc d
| d == maxBound = minBound
| otherwise = succ d
data Direction = North | East | South | West
deriving (Eq, Enum, Bounded, CyclicEnum, Show)
--instance CyclicEnum Direction
data Turn = TNone | TLeft | TRight | TAround
deriving (Eq, Enum, Bounded, BoundedEnum)
orient :: Turn -> Direction -> Direction
orient TNone = id
orient TLeft = cpred
orient TRight = csucc
orient TAround = cpred . cpred
findTurn :: Direction -> Direction -> Turn
findTurn d1 d2 = head $ filter (\t -> orient t d1 == d2) range
-- standalone deriving
deriving instance BoundedEnum Direction
deriving instance Ord Turn
test :: Bool
test = sort (nub [ findTurn d1 d2 | d1 <- range, d2 <- range ]) == range
main = do
putStr "Locator test: "
print test