{-# LANGUAGE DeriveDataTypeable #-} -- | A newtype around a list of Strings which represent the usernames -- to watch. This is all to avoid an orphan instance of Configured -- for [String] if we had defined one in e.g. OptionalConfiguration. -- module Usernames ( Usernames(..) ) where -- DC is needed only for the DCT.Configured instance of String. import qualified Data.Configurator as DC() import qualified Data.Configurator.Types as DCT import Data.Data ( Data ) import Data.Monoid ( Monoid(..) ) import Data.Typeable ( Typeable ) import System.Console.CmdArgs.Default ( Default(..) ) -- | Wrapper around a list of strings (usernames). -- newtype Usernames = Usernames { get_usernames :: [String] } deriving (Data, Show, Typeable) instance Default Usernames where -- | The default list of usernames is empty. -- def = Usernames [] -- | The 'Monoid' instance for 'Usernames' uses an -- 'Monoid' instance for lists. -- instance Monoid Usernames where -- | The \"empty\" 'Usernames' simply wraps an empty list. mempty = Usernames [] -- | This mappend is a little funny; it always chooses the second -- list if that list is nonempty. Otherwise, it chooses the -- first. This is actually associative! u1 `mappend` u2 | null (get_usernames u2) = u1 | otherwise = u2 instance DCT.Configured Usernames where -- | This allows us to read a 'Usernames' object out of a -- Configurator config file. By default Configurator wouldn't know -- what to do, so we have to tell it that we expect a list, and if -- that list has strings in it, we can apply the Usernames -- constructor to it. convert (DCT.List xs) = fmap Usernames (mapM convert_string xs) where convert_string :: DCT.Value -> Maybe String convert_string = DCT.convert convert _ = Nothing