weekdaze-0.0.0.1: src-lib/WeekDaze/Model/TimetableAxisTraversal.hs
{-
Copyright (C) 2013-2015 Dr. Alistair Ward
This file is part of WeekDaze.
WeekDaze is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
WeekDaze is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with WeekDaze. If not, see <http://www.gnu.org/licenses/>.
-}
{- |
[@AUTHOR@] Dr. Alistair Ward
[@DESCRIPTION@] Defines a specific axis (& the sense in which that axis is traversed), in the three-dimensional coordinate-system used to describe a /timetable/.
-}
module WeekDaze.Model.TimetableAxisTraversal(
-- * Types
-- ** Type-synonyms
Sense,
-- ** Data-types
AxisTraversal(..),
-- * Constants
-- tag,
senseTag,
-- * Functions
maybeSenseToList,
invertSense,
-- ** Predicates
hasWildSense
) where
import Control.Arrow((&&&))
import qualified Control.Arrow
import qualified Control.DeepSeq
import qualified Data.Char
import qualified Data.Maybe
import qualified Text.XML.HXT.Arrow.Pickle as HXT
import qualified WeekDaze.Model.TimetableAxis as Model.TimetableAxis
import WeekDaze.Enhanced.EnhancedBool()
-- | Used to qualify SQL & XML.
tag :: String
tag = "timetableAxisTraversal"
-- | Used to qualify SQL & XML.
senseTag :: String
senseTag = "sense"
-- | Defines the direction of travel along an axis; 'True' being interpreted as positive & 'False' negative.
type Sense = Bool
-- | Defines an axis & the direction of travel along it.
data AxisTraversal = MkAxisTraversal {
getMaybeSense :: Maybe Sense, -- ^ Optionally defines the direction of travel along the axis.
getAxis :: Model.TimetableAxis.Axis -- ^ Defines which of the axes to traverse.
} deriving Eq
instance Read AxisTraversal where
readsPrec _ [] = []
readsPrec _ s@(c : remainder)
| Data.Char.isSpace c = reads remainder -- Consume.
| otherwise = case c of
'+' -> Control.Arrow.first (MkAxisTraversal $ Just True) `map` reads remainder
'-' -> Control.Arrow.first (MkAxisTraversal $ Just False) `map` reads remainder
_ -> Control.Arrow.first (MkAxisTraversal Nothing) `map` reads s -- Wild sense.
instance Show AxisTraversal where
showsPrec _ axisTraversal = showString (
Data.Maybe.maybe "" (\sense -> if sense then "+" else "-") $ getMaybeSense axisTraversal
) . shows (getAxis axisTraversal)
instance HXT.XmlPickler AxisTraversal where
xpickle = HXT.xpElem tag . HXT.xpWrap (
uncurry MkAxisTraversal, -- Construct from a Pair.
getMaybeSense &&& getAxis -- Deconstruct to a Pair.
) $ HXT.xpAttrImplied senseTag HXT.xpickle {-Maybe Sense-} `HXT.xpPair` HXT.xpickle {-TimetableAxis-}
instance Control.DeepSeq.NFData AxisTraversal where
rnf = Control.DeepSeq.rnf . (getMaybeSense &&& getAxis)
-- | Interpret a sense-specification.
maybeSenseToList :: Maybe Sense -> [Sense]
maybeSenseToList = Data.Maybe.maybe [minBound .. maxBound] return {-to List-monad-}
-- | Construct a traversal which goes the other way along the same axis.
invertSense :: AxisTraversal -> AxisTraversal
invertSense (MkAxisTraversal (Just sense) axis) = MkAxisTraversal (Just $ not sense) axis
invertSense x@(MkAxisTraversal Nothing _) = x
-- | True if the sense is ill-defined.
hasWildSense :: AxisTraversal -> Bool
hasWildSense = Data.Maybe.isNothing . getMaybeSense