module Propellor.Types.Info (
Info,
IsInfo(..),
addInfo,
toInfo,
fromInfo,
mapInfo,
propagatableInfo,
InfoVal(..),
fromInfoVal,
Typeable,
) where
import Data.Dynamic
import Data.Maybe
import Data.Monoid
import Prelude
newtype Info = Info [InfoEntry]
deriving (Monoid, Show)
data InfoEntry where
InfoEntry :: (IsInfo v, Typeable v) => v -> InfoEntry
instance Show InfoEntry where
show (InfoEntry v) = show v
extractInfoEntry :: Typeable v => InfoEntry -> Maybe v
extractInfoEntry (InfoEntry v) = cast v
class (Typeable v, Monoid v, Show v) => IsInfo v where
propagateInfo :: v -> Bool
addInfo :: IsInfo v => Info -> v -> Info
addInfo (Info l) v = Info (InfoEntry v:l)
toInfo :: IsInfo v => v -> Info
toInfo = addInfo mempty
fromInfo :: IsInfo v => Info -> v
fromInfo (Info l) = mconcat (mapMaybe extractInfoEntry (reverse l))
mapInfo :: IsInfo v => (v -> v) -> Info -> Info
mapInfo f (Info l) = Info (map go l)
where
go i = case extractInfoEntry i of
Nothing -> i
Just v -> InfoEntry (f v)
propagatableInfo :: Info -> Info
propagatableInfo (Info l) = Info (filter (\(InfoEntry a) -> propagateInfo a) l)
data InfoVal v = NoInfoVal | InfoVal v
deriving (Typeable, Show)
instance Monoid (InfoVal v) where
mempty = NoInfoVal
mappend _ v@(InfoVal _) = v
mappend v NoInfoVal = v
instance (Typeable v, Show v) => IsInfo (InfoVal v) where
propagateInfo _ = False
fromInfoVal :: InfoVal v -> Maybe v
fromInfoVal NoInfoVal = Nothing
fromInfoVal (InfoVal v) = Just v