content: --
  -- | Nickname equality subsystem.
  --
  -- This component is responsible for deciding whether two nicknames
  -- refer to the same person, for the purposes of @tell et al.  Nickname
  -- equality must be monadic because it uses mutable state maintained
  -- by the @link and @unlink commands.
  --
  -- Also provided is a concept of polynicks (by analogy to polytypes);
  -- polynicks can refer to an (open) set of nicknames.  For instance '@tell
  -- *lambdabot Why does X do Y' could tell a message to anyone who has
  -- identified as a lambdabot maintainer.  A polynick consists of a
  -- bar-separated list of (nicks or open terms); an open term is like a
  -- nick but preceded with a star.
  
  module Lambdabot.Util.NickEq
      ( Polynick
      , nickMatches
      , readPolynick
      , showPolynick
      
      , lookupMononickMap
      , mononickToPolynick
      ) where
  
  import Lambdabot.Message
  import Lambdabot.Monad
  import Lambdabot.Nick
  
  import Data.List (intercalate)
  import Data.List.Split (splitOn)
  import qualified Data.Map as M
  import Data.Maybe (mapMaybe)
  
  data Polynick = Polynick [Nick] deriving (Eq) -- for now
  
  -- |Determine if a nick matches a polynick.  The state is read at the
  -- point of binding.
  nickMatches :: LB (Nick -> Polynick -> Bool)
  nickMatches = return m'
      where
        m' nck (Polynick nck2) = nck `elem` nck2
  
  -- | Parse a read polynick.
  readPolynick :: Message a => a -> String -> Polynick
  readPolynick m = Polynick . map (parseNick (server m)) . splitOn "|"
  
  -- | Format a polynick.
  showPolynick :: Message a => a -> Polynick -> String
  showPolynick m (Polynick n) = intercalate "|" $ map (fmtNick (server m)) n
  
  -- | Convert a regular mononick into a polynick.
  mononickToPolynick :: Nick -> Polynick
  mononickToPolynick = Polynick . (:[])
  
  -- | Lookup (using a polynick) in a map keyed on mononicks.
  lookupMononickMap :: LB (Polynick -> M.Map Nick a -> [(Nick,a)])
  lookupMononickMap = return $ look'
      where look' (Polynick ns) m = mapMaybe (\n -> (,) n `fmap` M.lookup n m) ns
  