diff --git a/NEWS.md b/NEWS.md
--- a/NEWS.md
+++ b/NEWS.md
@@ -3,6 +3,30 @@
 
 
 
+irc-fun-types 0.2        2016-09-05
+===================================
+
+General, build and documentation changes:
+
+* Change module names
+* Build with stack
+
+New APIs, features and enhancements:
+
+* Nickname and Channel are now Hashable instances
+
+Bug fixes:
+
+* (None)
+
+Dependency changes:
+
+* (None)
+
+
+
+
+
 irc-fun-types 0.1.0.0 -- 2016-01-27
 ===================================
 
diff --git a/irc-fun-types.cabal b/irc-fun-types.cabal
--- a/irc-fun-types.cabal
+++ b/irc-fun-types.cabal
@@ -1,5 +1,5 @@
 name:                irc-fun-types
-version:             0.1.0.0
+version:             0.2
 synopsis:            Common types for IRC related packages
 description:
   This library provides types useful to programs and libraries working with
@@ -16,9 +16,9 @@
   require recognizing Unicode.
   .
   If you are writing a simple IRC client module, you can probably use
-  "Network.IRC.Fun.Types.Base", which contains the subset you'll likely need.
+  "Network.Irc.Types.Base", which contains the subset you'll likely need.
   But if you're writing an IRC message parser or serializer, you'll probably
-  want to use "Network.IRC.Fun.Types", which contains all the types.
+  want to use "Network.Irc.Types", which contains all the types.
 homepage:            http://hub.darcs.net/fr33domlover/irc-fun-types
 bug-reports:         https://notabug.org/fr33domlover/funbot/issues
 license:             PublicDomain
@@ -41,11 +41,12 @@
   location:            http://hub.darcs.net/fr33domlover/irc-fun-types
 
 library
-  exposed-modules:     Network.IRC.Fun.Types
-                     , Network.IRC.Fun.Types.Base
+  exposed-modules:     Network.Irc.Types
+                     , Network.Irc.Types.Base
   -- other-modules:       
   -- other-extensions:    
-  build-depends:       base >=4.7 && <5
+  build-depends:       base     >= 4.7 && < 5
+                     , hashable
                      , text
   hs-source-dirs:      src
   default-language:    Haskell2010
diff --git a/src/Network/IRC/Fun/Types.hs b/src/Network/IRC/Fun/Types.hs
deleted file mode 100644
--- a/src/Network/IRC/Fun/Types.hs
+++ /dev/null
@@ -1,833 +0,0 @@
-{- This file is part of irc-fun-types.
- -
- - Written in 2015, 2016 by fr33domlover <fr33domlover@riseup.net>.
- -
- - ♡ Copying is an act of love. Please copy, reuse and share.
- -
- - The author(s) have dedicated all copyright and related and neighboring
- - rights to this software to the public domain worldwide. This software is
- - distributed without any warranty.
- -
- - You should have received a copy of the CC0 Public Domain Dedication along
- - with this software. If not, see
- - <http://creativecommons.org/publicdomain/zero/1.0/>.
- -}
-
-module Network.IRC.Fun.Types
-    ( -- * Type Aliases, Newtypes, Other Basics
-      module Network.IRC.Fun.Types.Base
-      -- * Message Parts
-    , Prefix (..)
-    , UserAddress (..)
-    , Target (..)
-    , Address (..)
-    , Host (..)
-    , Command (..)
-      -- * Mask
-    , MaskPart (..)
-    , Mask (..)
-    , TargetMask (..)
-      -- * Message
-    , GenericMessage (..)
-    , SpecificMessage (..)
-    , MessageTarget (..)
-    , Query (..)
-    , Message (..)
-    , AnalysisError (..)
-    , ArgSpec (..)
-      -- * Modes
-    , UserMode (..)
-    , ChannelMode (..)
-    , ChannelModeType (..)
-      -- * Reply
-    , GenericReply (..)
-    , Reply (..)
-    , SpecificReply (..)
-    )
-where
-
-import Data.Text (Text)
-import Network.IRC.Fun.Types.Base
-
--------------------------------------------------------------------------------
--- Message Parts
--------------------------------------------------------------------------------
-
--- | IRC message prefix.
-data Prefix
-    -- | The server which sends the message
-    = PrefixServer Hostname
-    -- | The user which sends the message (if the message comes from a user)
-    | PrefixNick Nickname (Maybe Username) (Maybe Host)
-    deriving (Eq, Show)
-
--- | User address containing a name part (as in "user") and an optional host
--- part (as in "user@host").
-data UserAddress = UserAddress Username (Maybe Host) deriving (Eq, Show)
-
--- | Some IRC commands operate on a target, that is either a single user or an
--- entire IRC server.
-data Target = NickTarget Nickname | ServerTarget Hostname deriving (Eq, Show)
-
--- | An IP address.
-data Address = IPv4 Text | IPv6 Text deriving (Eq, Show)
-
--- | A host, either a hostname (e.g. @irc.freenode.net@) or an IP address, or a
--- cloak assigned by the server.
-data Host = HostByName Hostname | HostByAddr Address | HostCloak Text
-    deriving (Eq, Show)
-
--- | An IRC command code. Either a named command, or a numeric one.
-data Command = NamedCmd CmdName | NumericCmd CmdNumber
-    deriving (Eq, Show)
-
--------------------------------------------------------------------------------
--- Masks
--------------------------------------------------------------------------------
-
--- | Part of a 'Mask'.
-data MaskPart
-    -- | A literal character.
-    = MaskChar Char
-    -- | A wildcard which matches a single character.
-    | MaskWildOne
-    -- | A wildcard which matches zero or more characters.
-    | MaskWildMany
-    deriving (Eq, Show)
-
--- | A pattern for matching host and server names. A mask in the protocol is a
--- string which consists of literal characters and wildcards. There are two
--- wildcards: @'?'@, which matches a single character; @'*'@, which matches any
--- number of characters (zero or more).
-newtype Mask = Mask [MaskPart] deriving (Eq, Show)
-
--- | Some IRC command parameters are targets, and one way to specify a target
--- is using a 'Mask'.
-data TargetMask
-    -- | Host mask, prefixed with @'#'@ in the protocol. Selects all the users
-    -- whose host matches the mask.
-    = HostMask Mask
-    -- | Server mask, prefixed with @'$'@ in the protocol. Selects all the
-    -- users connected to a server which matches the mask.
-    | ServerMask Mask
-    deriving (Eq, Show)
-
--------------------------------------------------------------------------------
--- Message
--------------------------------------------------------------------------------
-
--- | A generic IRC message. It consists of a sender prefix, command name
--- (string or numeric) and optionally a list of parameters.
-data GenericMessage = GenericMessage
-    { gmPrefix  :: Maybe Prefix
-    , gmCommand :: Command
-    , gmParams  :: [Text]
-    }
-    deriving Show
-
--- | An IRC message of a specific type. This includes only messages whose
--- command is a name. Messages with a numeric command are handled in the
--- "Network.IRC.Fun.Messages.Reply" module.
-data SpecificMessage = SpecificMessage (Maybe Prefix) Message deriving Show
-
--- | Some IRC commands have targets. For example, to which channel to send a
--- given text message. Targets are specified as parameters in IRC messages.
-data MessageTarget
-    -- | An IRC channel.
-    = ChannelTarget Channel
-    -- | An IRC user. Possible combinations in the protocol are:
-    --
-    -- * Address              (address host is required)
-    -- * Address and server   (address host is optional)
-    -- * Nickname
-    -- * Nickname and address (address host is required)
-    | UserTarget (Maybe Nickname) (Maybe UserAddress) (Maybe Hostname)
-    -- | A mask which matches the server or host of the users to whom the
-    -- message should be sent.
-    | MaskTarget TargetMask
-    deriving Show
-
--- | A server query. Can be sent through a 'StatsMessage'.
-data Query
-    -- | TODO
-    = Connections
-    -- | TODO
-    | CommandUsage
-    -- | TODO
-    | PrivilegedUsers
-    -- | TODO
-    | Uptime
-    -- | TODO
-    | OtherQuery Char
-    deriving Show
-
--- TODO in all the either-servername-mask occurences, make sure in the RFC
--- that they are "<target> may contain wildcards" cases, and replace them with
--- plain Hostname - let's treat mask as a user mask (for bans etc.)
--- TODO in all the <target> cases, do they mean a user can be specified too,
--- to mean "the server this user is connected to"? try with some IRC servers
--- over telnet, and change Hostname to Target if yes. Note that servername
--- has '.' chars while a nickname can't, so that's how one tells which is which
--- Also compare with existing irc packages, how they model these messages
-
--- | An IRC message of specific type (excluding the optional sender prefix, see
--- 'SpecificMessage').
-data Message
--- Connection registration
-    = PassMessage Password
-    | NickMessage Nickname
-    -- | first bool = whether invisible, second bool = whether sees wallops
-    | UserMessage Username Bool Bool RealName
-    | OperMessage Username Password
-    -- | first list: modes to remove (-), second list: modes to add (+)
-    | UserModeMessage Nickname [UserMode] [UserMode]
-    | ServiceMessage Nickname Mask Text
-    | QuitMessage (Maybe Comment)
-    | SQuitMessage Hostname Comment
--- Channel operations
-    | JoinMessage (Maybe ([Channel], [ChannelKey]))
-    | PartMessage [Channel] (Maybe Comment)
-    -- first: remove (-), second: add/set (+)
-    | ChannelModeMessage [ChannelMode] [ChannelMode]
-    | TopicMessage Channel (Maybe ChannelTopic)
-    | NamesMessage [Channel] (Maybe Hostname)
-    | ListMessage [Channel] (Maybe Hostname)
-    | InviteMessage Nickname Channel
-    | KickMessage [Channel] [Username] (Maybe Comment)
--- Sending messages
-    | PrivMsgMessage MessageTarget MsgContent
-    | PrivActionMessage MessageTarget MsgContent
-    | NoticeMessage MessageTarget MsgContent
--- Server queries and commands
-    | MotdMessage (Maybe Hostname)
-    | LusersMessage (Maybe (Mask, Maybe Hostname))
-    | VersionMessage (Maybe (Either Hostname Mask))
-    | StatsMessage (Maybe (Query, Maybe (Either Hostname Mask)))
-    | LinksMessage (Maybe (Maybe (Either Hostname Mask), Mask))
-    | TimeMessage (Maybe (Either Hostname Mask))
-    | ConnectMessage Hostname PortNumber (Either Hostname Mask)
-    | TraceMessage (Maybe Target)
-    | AdminMessage (Maybe Target)
-    | InfoMessage (Maybe Target)
--- Service query and commands
-    | ServlistMessage (Maybe (Mask, Maybe Text))
-    | SQueryMessage ServiceName MsgContent
--- User based queries
-    | WhoMessage (Maybe (Mask, Bool))
-    | WhoisMessage (Maybe Hostname) [Mask]
-    | WhowasMessage [Nickname] (Maybe (Int, Maybe Hostname))
--- Miscellaneous messages
-    | KillMessage Nickname Comment
-    | PingMessage Hostname (Maybe Hostname)
-    | PongMessage Hostname (Maybe Hostname)
-    | ErrorMessage Text
--- Optional features
-    | AwayMessage (Maybe MsgContent)
-    | RehashMessage
-    | DieMessage
-    | RestartMessage
-    | SummonMessage Username (Maybe (Hostname, Maybe Channel))
-    | UsersMessage (Maybe Hostname)
-    | WallopsMessage MsgContent
-    | UserhostMessage [Nickname]
-    | IsonMessage [Nickname]
-    deriving Show
-
--------------------------------------------------------------------------------
--- Modes
--------------------------------------------------------------------------------
-
--- | TODO
-data UserMode
-    -- http://toxin.jottit.com/freenode_user_modes
-    = UModeInvisible
-    | UModeCallerID
-    | UModeSeeWallops
-    | UModeDeaf
-    | UModeNoForwarding
-    | UModeBlockUnidentified
-    | UModeConnectedViaSSL
-    -- from the irc rfc, MODE message (section 3.1.5)
-    | UModeAway
-    | UModeRestricted
-    | UModeOperator
-    | UModeLocalOperator
-    | UModeSeeNotices
-    | UModeOther Char
-    deriving (Eq, Show)
-
--- | TODO
-data ChannelMode
-    = CModeCreator
-    | CModeOperator
-    | CModeVoice
-    | CModeAnonymous
-    | CModeInviteOnly
-    | CModeModerated
-    | CModeNoMessagesFromOutside
-    | CModeQuiet
-    | CModePrivate
-    | CModeSecret
-    | CModeServerReop
-    | CModeTopicSettableByChannelOpOnly
-    | CModeKey (Maybe ChannelKey)
-    | CModeUserLimit (Maybe Int)
-    | CModeBanMask (Maybe Mask)
-    | CModeExceptionMask (Maybe Mask)
-    | CModeInvitationMask (Maybe Mask)
-    | CModeOther Char [Text]
-    | CModeFreenodeQuiet (Maybe Mask)
-    deriving (Eq, Show)
-
-data ChannelModeType
-    = ModeTypeList
-    | ModeTypeSetting
-    | ModeTypeMaybeSetting
-    | ModeTypeFlag
-
--------------------------------------------------------------------------------
--- Reply
--------------------------------------------------------------------------------
-
--- | TODO
-data CommandResponseCode
-    -- | TODO
-    = ReplyWelcome
-    -- | TODO
-    | ReplyYourHost
-    -- | TODO
-    | ReplyCreated
-    -- | TODO
-    | ReplyMyInfo
-    -- | TODO
-    | ReplyBounce
-    -- | TODO
-    | ReplyUserHost
-    -- | TODO
-    | ReplyIsOn
-    -- | TODO
-    | ReplyAway
-    -- | TODO
-    | ReplyUnAway
-    -- | TODO
-    | ReplyNoAway
-    -- | TODO
-    | ReplyWhoIsUser
-    -- | TODO
-    | ReplyWhoIsServer
-    -- | TODO
-    | ReplyWhoIsOperator
-    -- | TODO
-    | ReplyWhoIsIdle
-    -- | TODO
-    | ReplyEndOfWhoIs
-    -- | TODO
-    | ReplyWhoIsChannels
-    -- | TODO
-    | ReplyWhoWasUser
-    -- | TODO
-    | ReplyEndOfWhoWas
-    -- | TODO
-    | ReplyListStart
-    -- | TODO
-    | ReplyList
-    -- | TODO
-    | ReplyListEnd
-    -- | TODO
-    | ReplyUniqueOpIs
-    -- | TODO
-    | ReplyChannelModeIs
-    -- | TODO
-    | ReplyNoTopic
-    -- | TODO
-    | ReplyTopic
-    -- | TODO
-    | ReplyInviting
-    -- | TODO
-    | ReplySummoning
-    -- | TODO
-    | ReplyInviteList
-    -- | TODO
-    | ReplyEndOfInviteList
-    -- | TODO
-    | ReplyExceptList
-    -- | TODO
-    | ReplyEndOfExceptList
-    -- | TODO
-    | ReplyVersion
-    -- | TODO
-    | ReplyWhoReply
-    -- | TODO
-    | ReplyEndOfWho
-    -- | TODO
-    | ReplyNameReply
-    -- | TODO
-    | ReplyEndOfNames
-    -- | TODO
-    | ReplyLinks
-    -- | TODO
-    | ReplyEndOfLinks
-    -- | TODO
-    | ReplyBanList
-    -- | TODO
-    | ReplyEndOfBanList
-    -- | TODO
-    | ReplyInfo
-    -- | TODO
-    | ReplyEndOfInfo
-    -- | TODO
-    | ReplyMotdStart
-    -- | TODO
-    | ReplyMessageOfTheDay
-    -- | TODO
-    | ReplyEndOfMessageOfTheDay
-    -- | TODO
-    | ReplyYoureOper
-    -- | TODO
-    | ReplyRehashing
-    -- | TODO
-    | ReplyYoureService
-    -- | TODO
-    | ReplyTime
-    -- | TODO
-    | ReplyUsersStart
-    -- | TODO
-    | ReplyUsers
-    -- | TODO
-    | ReplyEndOfUsers
-    -- | TODO
-    | ReplyNoUsers
-    -- | TODO
-    | ReplyTraceLink
-    -- | TODO
-    | ReplyTraceConnecting
-    -- | TODO
-    | ReplyTraceHandshake
-    -- | TODO
-    | ReplyTraceUnknown
-    -- | TODO
-    | ReplyTraceOperator
-    -- | TODO
-    | ReplyTraceUser
-    -- | TODO
-    | ReplyTraceServer
-    -- | TODO
-    | ReplyTraceService
-    -- | TODO
-    | ReplyTraceNewType
-    -- | TODO
-    | ReplyTraceClass
-    -- | TODO
-    | ReplyTraceReconnect
-    -- | TODO
-    | ReplyTraceLog
-    -- | TODO
-    | ReplyTraceEnd
-    -- | TODO
-    | ReplyStatsLinkInfo
-    -- | TODO
-    | ReplyStatsCommands
-    -- | TODO
-    | ReplyEndOfStats
-    -- | TODO
-    | ReplyStatsUptime
-    -- | TODO
-    | ReplyStatsOLine
-    -- | TODO
-    | ReplyUModeIs
-    -- | TODO
-    | ReplyServList
-    -- | TODO
-    | ReplyServListEnd
-    -- | TODO
-    | ReplyLuserClient
-    -- | TODO
-    | ReplyLuserOp
-    -- | TODO
-    | ReplyLuserUnknown
-    -- | TODO
-    | ReplyLuserChannels
-    -- | TODO
-    | ReplyLuserMe
-    -- | TODO
-    | ReplyAdminMe
-    -- | TODO
-    | ReplyAdminLocation1
-    -- | TODO
-    | ReplyAdminLocation2
-    -- | TODO
-    | ReplyAdminEmail
-    -- | TODO
-    | ReplyTryAgain
-    -- | TODO
-    | ReplyFreenodeISupport
-    deriving (Eq, Show)
-
-data ErrorReplyCode
-    -- | TODO
-    = ErrorNoSuchNick
-    -- | TODO
-    | ErrorNoSuchServer
-    -- | TODO
-    | ErrorNoSuchChannel
-    -- | TODO
-    | ErrorCannotSendToChannel
-    -- | TODO
-    | ErrorTooManyChannels
-    -- | TODO
-    | ErrorWasNoSuchNick
-    -- | TODO
-    | ErrorTooManyTargets
-    -- | TODO
-    | ErrorNoSuchService
-    -- | TODO
-    | ErrorNoOrigin
-    -- | TODO
-    | ErrorNoRecipient
-    -- | TODO
-    | ErrorNoTextToSend
-    -- | TODO
-    | ErrorNoTopLevel
-    -- | TODO
-    | ErrorWildTopLevel
-    -- | TODO
-    | ErrorBadMask
-    -- | TODO
-    | ErrorUnknownCommand
-    -- | TODO
-    | ErrorNoMessageOfTheDay
-    -- | TODO
-    | ErrorNoAdminInfo
-    -- | TODO
-    | ErrorFileError
-    -- | TODO
-    | ErrorNoNicknameGiven
-    -- | TODO
-    | ErrorErroneousNickname
-    -- | TODO
-    | ErrorNicknameInUse
-    -- | TODO
-    | ErrorNickCollision
-    -- | TODO
-    | ErrorUnavailableResource
-    -- | TODO
-    | ErrorUserNotInChannel
-    -- | TODO
-    | ErrorNotOnChannel
-    -- | TODO
-    | ErrorUserOnChannel
-    -- | TODO
-    | ErrorNoLogin
-    -- | TODO
-    | ErrorSummonDisabled
-    -- | TODO
-    | ErrorUsersDisabled
-    -- | TODO
-    | ErrorNotRegistered
-    -- | TODO
-    | ErrorNeedMoreParams
-    -- | TODO
-    | ErrorAlreadyRegistered
-    -- | TODO
-    | ErrorNoPermissionForHost
-    -- | TODO
-    | ErrorPasswordMismatch
-    -- | TODO
-    | ErrorYoureBannedCreep
-    -- | TODO
-    | ErrorYouWillBeBanned
-    -- | TODO
-    | ErrorKeySet
-    -- | TODO
-    | ErrorChannelIsFull
-    -- | TODO
-    | ErrorUnknownMode
-    -- | TODO
-    | ErrorInviteOnlyChannel
-    -- | TODO
-    | ErrorBannedFromChannel
-    -- | TODO
-    | ErrorBadChannelKey
-    -- | TODO
-    | ErrorBadChannelMask
-    -- | TODO
-    | ErrorNoChannelModes
-    -- | TODO
-    | ErrorBanListFull
-    -- | TODO
-    | ErrorNoPrivileges
-    -- | TODO
-    | ErrorChannelOpPrivilegesNeeded
-    -- | TODO
-    | ErrorCantKillServer
-    -- | TODO
-    | ErrorRestricted
-    -- | TODO
-    | ErrorUniqueOpPrivilegesNeeded
-    -- | TODO
-    | ErrorNoOperHost
-    -- | TODO
-    | ErrorUModeUnknownFlag
-    -- | TODO
-    | ErrorUsersDontMatch
-    deriving (Eq, Show)
-
-data ReservedReplyCode
-    -- | TODO
-    = ReservedReplyServiceInfo
-    -- | TODO
-    | ReservedReplyEndOfServices
-    -- | TODO
-    | ReservedReplyService
-    -- | TODO
-    | ReservedReplyNone
-    -- | TODO
-    | ReservedReplyWhoIsChannelOp
-    -- | TODO
-    | ReservedReplyKillDone
-    -- | TODO
-    | ReservedReplyClosing
-    -- | TODO
-    | ReservedReplyCloseEnd
-    -- | TODO
-    | ReservedReplyInfoStart
-    -- | TODO
-    | ReservedReplyMyPortIs
-    -- | TODO
-    | ReservedReplyStatsCLine
-    -- | TODO
-    | ReservedReplyStatsNLine
-    -- | TODO
-    | ReservedReplyStatsILine
-    -- | TODO
-    | ReservedReplyStatsKLine
-    -- | TODO
-    | ReservedReplyStatsQLine
-    -- | TODO
-    | ReservedReplyStatsYLine
-    -- | TODO
-    | ReservedReplyStatsVLine
-    -- | TODO
-    | ReservedReplyStatsLLine
-    -- | TODO
-    | ReservedReplyStatsHLine
-    -- | TODO
-    | ReservedReplyStatsSLine
-    -- | TODO
-    | ReservedReplyStatsPing
-    -- | TODO
-    | ReservedReplyStatsBLine
-    -- | TODO
-    | ReservedReplyStatsDLine
-    deriving (Eq, Show)
-
--- | TODO
-data ReservedErrorCode
-    -- | TODO
-    = ReservedErrorNoServiceHost
-    deriving (Eq, Show)
-
--- | TODO
-data GenericReply = GenericReply
-    { grSender :: Hostname
-    , grCode   :: CmdNumber
-    , grTarget :: Target
-    , grParams :: [Parameter]
-    }
-    deriving Show
-
--- | TODO
-data Reply
-    -- | TODO
-    = WelcomeReply
-    -- | TODO
-    | YourHostReply
-    -- | TODO
-    | CreatedReply
-    -- | TODO
-    | MyInfoReply
-    -- | TODO
-    | BounceReply
-    -- | TODO
-    | ISupportReply
-    -- | TODO
-    | UserHostReply
-    -- | TODO
-    | IsOnReply
-    -- | TODO
-    | AwayReply
-    -- | TODO
-    | UnAwayReply
-    -- | TODO
-    | NoAwayReply
-    -- | TODO
-    | WhoIsUserReply
-    -- | TODO
-    | WhoIsServerReply
-    -- | TODO
-    | WhoIsOperatorReply
-    -- | TODO
-    | WhoIsIdleReply
-    -- | TODO
-    | EndOfWhoIsReply
-    -- | TODO
-    | WhoIsChannelsReply
-    -- | TODO
-    | WhoWasUserReply
-    -- | TODO
-    | EndOfWhoWasReply
-    -- | TODO
-    | ListStartReply
-    -- | TODO
-    | ListReply
-    -- | TODO
-    | ListEndReply
-    -- | TODO
-    | UniqueOpIsReply
-    -- | TODO
-    | ChannelModeIsReply
-    -- | TODO
-    | NoTopicReply
-    -- | TODO
-    | TopicReply
-    -- | TODO
-    | InvitingReply
-    -- | TODO
-    | SummoningReply
-    -- | TODO
-    | InviteListReply
-    -- | TODO
-    | EndOfInviteListReply
-    -- | TODO
-    | ExceptListReply
-    -- | TODO
-    | EndOfExceptListReply
-    -- | TODO
-    | VersionReply
-    -- | TODO
-    | WhoReply
-    -- | TODO
-    | EndOfWhoReply
-    -- | Lists members of IRC channels. Sent when JOINing a channel to list the
-    -- users in that channel, or as a response to the NAMES command.
-    | NamesReply ChannelPrivacy Channel [(Privilege, Nickname)]
-    -- | Sent after a sequence of 0 or more 'NameReply's, to signal that the
-    -- list transmission is finished.
-    | EndOfNamesReply
-    -- | TODO
-    | LinksReply
-    -- | TODO
-    | EndOfLinksReply
-    -- | TODO
-    | BanListReply
-    -- | TODO
-    | EndOfBanListReply
-    -- | TODO
-    | InfoReply
-    -- | TODO
-    | EndOfInfoReply
-    -- | TODO
-    | MotdStartReply
-    -- | TODO
-    | MessageOfTheDayReply
-    -- | TODO
-    | EndOfMessageOfTheDayReply
-    -- | TODO
-    | YoureOperReply
-    -- | TODO
-    | RehashingReply
-    -- | TODO
-    | YoureServiceReply
-    -- | TODO
-    | TimeReply
-    -- | TODO
-    | UsersStartReply
-    -- | TODO
-    | UsersReply
-    -- | TODO
-    | EndOfUsersReply
-    -- | TODO
-    | NoUsersReply
-    -- | TODO
-    | TraceLinkReply
-    -- | TODO
-    | TraceConnectingReply
-    -- | TODO
-    | TraceHandshakeReply
-    -- | TODO
-    | TraceUnknownReply
-    -- | TODO
-    | TraceOperatorReply
-    -- | TODO
-    | TraceUserReply
-    -- | TODO
-    | TraceServerReply
-    -- | TODO
-    | TraceServiceReply
-    -- | TODO
-    | TraceNewTypeReply
-    -- | TODO
-    | TraceClassReply
-    -- | TODO
-    | TraceReconnectReply
-    -- | TODO
-    | TraceLogReply
-    -- | TODO
-    | TraceEndReply
-    -- | TODO
-    | StatsLinkInfoReply
-    -- | TODO
-    | StatsCommandsReply
-    -- | TODO
-    | EndOfStatsReply
-    -- | TODO
-    | StatsUptimeReply
-    -- | TODO
-    | StatsOLineReply
-    -- | TODO
-    | UModeIsReply
-    -- | TODO
-    | ServListReply
-    -- | TODO
-    | ServListEndReply
-    -- | TODO
-    | LuserClientReply
-    -- | TODO
-    | LuserOpReply
-    -- | TODO
-    | LuserUnknownReply
-    -- | TODO
-    | LuserChannelsReply
-    -- | TODO
-    | LuserMeReply
-    -- | TODO
-    | AdminMeReply
-    -- | TODO
-    | AdminLocation1Reply
-    -- | TODO
-    | AdminLocation2Reply
-    -- | TODO
-    | AdminEmailReply
-    -- | TODO
-    | TryAgainReply
-    deriving (Eq, Show)
-
--- | An IRC server numeric reply of a specific type.
-data SpecificReply = SpecificReply Hostname Target Reply deriving Show
-
--- | Specifies the number of parameter a certain IRC message type accepts.
-data ArgSpec
-    = Exactly Int
-    | AtLeast Int
-    | AtMost Int
-    | Between Int Int
-    | OneOf [Int]
-    deriving (Show)
-
--- | An error occuring while analyzing a parsed IRC protocol message into a
--- specific message type, such as 'JoinMessage'.
-data AnalysisError
-    = WrongNumArgs Int (Maybe ArgSpec)
-    | InvalidArg (Maybe Int) (Maybe Text) (Maybe Text)
-    | OtherError Text
-    deriving (Show)
diff --git a/src/Network/IRC/Fun/Types/Base.hs b/src/Network/IRC/Fun/Types/Base.hs
deleted file mode 100644
--- a/src/Network/IRC/Fun/Types/Base.hs
+++ /dev/null
@@ -1,96 +0,0 @@
-{- This file is part of irc-fun-types.
- -
- - Written in 2015, 2016 by fr33domlover <fr33domlover@riseup.net>.
- -
- - ♡ Copying is an act of love. Please copy, reuse and share.
- -
- - The author(s) have dedicated all copyright and related and neighboring
- - rights to this software to the public domain worldwide. This software is
- - distributed without any warranty.
- -
- - You should have received a copy of the CC0 Public Domain Dedication along
- - with this software. If not, see
- - <http://creativecommons.org/publicdomain/zero/1.0/>.
- -}
-
--- For deriving trivial no-op instances for newtypes
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-
-module Network.IRC.Fun.Types.Base
-    ( Hostname (..)
-    , ServiceName (..)
-    , Username (..)
-    , Nickname (..)
-    , Channel (..)
-    , CmdName (..)
-    , CmdNumber (..)
-    , Parameter
-    , MsgContent (..)
-    , Password (..)
-    , ChannelKey (..)
-    , ChannelTopic (..)
-    , RealName (..)
-    , Comment (..)
-    , PortNumber (..)
-    , Privilege (..)
-    , ChannelPrivacy (..)
-    )
-where
-
-import Data.Monoid (Monoid)
-import Data.String (IsString)
-import Data.Text (Text)
-
--- | IRC server hostname, e.g. @orwell.freenode.net@
-newtype Hostname = Hostname { unHostname :: Text } deriving (Eq, Show)
-
--- | An IRC service name.
-newtype ServiceName = ServiceName { unServiceName :: Text } deriving (Eq, Show)
-
--- | System user name, i.e. the first part of user\@host.tld
-newtype Username = Username { unUsername :: Text } deriving (Eq, Show)
-
--- | IRC nickname
-newtype Nickname = Nickname { unNickname :: Text } deriving (Eq, Show)
-
--- | IRC channel name (including the prefix character), e.g. @#freepost@
-newtype Channel = Channel { unChannel :: Text } deriving (Eq, Show)
-
--- | IRC protocol command name, i.e. @PRIVMSG@
-newtype CmdName = CmdName { unCmdName :: Text } deriving (Eq, Show)
-
--- | IRC protocol numeric command number
-newtype CmdNumber = CmdNumber { unCmdNumber :: Int } deriving (Eq, Show)
-
--- | IRC message parameter, e.g. second word in @JOIN #freepost@
-type Parameter = Text
-
--- | Chat message content, i.e. a message or a part of a text message meant to
--- be sent or received between people through IRC.
-newtype MsgContent = MsgContent { unMsgContent :: Text }
-    deriving (Show, Monoid, IsString)
-
--- | IRC connection password.
-newtype Password = Password { unPassword :: Text } deriving (Eq, Show)
-
--- | IRC channel password.
-newtype ChannelKey = ChannelKey { unChannelKey :: Text } deriving (Eq, Show)
-
--- | IRC channel topic line.
-newtype ChannelTopic = ChannelTopic { unChannelTopic :: Text } deriving Show
-
--- | A user's \"real name\" as kept by the IRC server.
-newtype RealName = RealName { unRealName :: Text } deriving Show
-
--- | An optional comment used by several IRC commands, e.g. a part message,
--- which is a line shown when a user leaves a channel.
-newtype Comment = Comment { unComment :: Text } deriving Show
-
--- | Network port number.
-newtype PortNumber = PortNumber { unPortNumber :: Int } deriving (Eq, Show)
-
--- | IRC privilege status for a user in the context of a specific channel.
-data Privilege = Regular | Voice | Operator deriving (Eq, Show)
-
--- | IRC channel privacy settings.
-data ChannelPrivacy = Secret | Private | Public deriving (Eq, Show)
diff --git a/src/Network/Irc/Types.hs b/src/Network/Irc/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Irc/Types.hs
@@ -0,0 +1,833 @@
+{- This file is part of irc-fun-types.
+ -
+ - Written in 2015, 2016 by fr33domlover <fr33domlover@riseup.net>.
+ -
+ - ♡ Copying is an act of love. Please copy, reuse and share.
+ -
+ - The author(s) have dedicated all copyright and related and neighboring
+ - rights to this software to the public domain worldwide. This software is
+ - distributed without any warranty.
+ -
+ - You should have received a copy of the CC0 Public Domain Dedication along
+ - with this software. If not, see
+ - <http://creativecommons.org/publicdomain/zero/1.0/>.
+ -}
+
+module Network.Irc.Types
+    ( -- * Type Aliases, Newtypes, Other Basics
+      module Network.Irc.Types.Base
+      -- * Message Parts
+    , Prefix (..)
+    , UserAddress (..)
+    , Target (..)
+    , Address (..)
+    , Host (..)
+    , Command (..)
+      -- * Mask
+    , MaskPart (..)
+    , Mask (..)
+    , TargetMask (..)
+      -- * Message
+    , GenericMessage (..)
+    , SpecificMessage (..)
+    , MessageTarget (..)
+    , Query (..)
+    , Message (..)
+    , AnalysisError (..)
+    , ArgSpec (..)
+      -- * Modes
+    , UserMode (..)
+    , ChannelMode (..)
+    , ChannelModeType (..)
+      -- * Reply
+    , GenericReply (..)
+    , Reply (..)
+    , SpecificReply (..)
+    )
+where
+
+import Data.Text (Text)
+import Network.Irc.Types.Base
+
+-------------------------------------------------------------------------------
+-- Message Parts
+-------------------------------------------------------------------------------
+
+-- | IRC message prefix.
+data Prefix
+    -- | The server which sends the message
+    = PrefixServer Hostname
+    -- | The user which sends the message (if the message comes from a user)
+    | PrefixNick Nickname (Maybe Username) (Maybe Host)
+    deriving (Eq, Show)
+
+-- | User address containing a name part (as in "user") and an optional host
+-- part (as in "user@host").
+data UserAddress = UserAddress Username (Maybe Host) deriving (Eq, Show)
+
+-- | Some IRC commands operate on a target, that is either a single user or an
+-- entire IRC server.
+data Target = NickTarget Nickname | ServerTarget Hostname deriving (Eq, Show)
+
+-- | An IP address.
+data Address = IPv4 Text | IPv6 Text deriving (Eq, Show)
+
+-- | A host, either a hostname (e.g. @irc.freenode.net@) or an IP address, or a
+-- cloak assigned by the server.
+data Host = HostByName Hostname | HostByAddr Address | HostCloak Text
+    deriving (Eq, Show)
+
+-- | An IRC command code. Either a named command, or a numeric one.
+data Command = NamedCmd CmdName | NumericCmd CmdNumber
+    deriving (Eq, Show)
+
+-------------------------------------------------------------------------------
+-- Masks
+-------------------------------------------------------------------------------
+
+-- | Part of a 'Mask'.
+data MaskPart
+    -- | A literal character.
+    = MaskChar Char
+    -- | A wildcard which matches a single character.
+    | MaskWildOne
+    -- | A wildcard which matches zero or more characters.
+    | MaskWildMany
+    deriving (Eq, Show)
+
+-- | A pattern for matching host and server names. A mask in the protocol is a
+-- string which consists of literal characters and wildcards. There are two
+-- wildcards: @'?'@, which matches a single character; @'*'@, which matches any
+-- number of characters (zero or more).
+newtype Mask = Mask [MaskPart] deriving (Eq, Show)
+
+-- | Some IRC command parameters are targets, and one way to specify a target
+-- is using a 'Mask'.
+data TargetMask
+    -- | Host mask, prefixed with @'#'@ in the protocol. Selects all the users
+    -- whose host matches the mask.
+    = HostMask Mask
+    -- | Server mask, prefixed with @'$'@ in the protocol. Selects all the
+    -- users connected to a server which matches the mask.
+    | ServerMask Mask
+    deriving (Eq, Show)
+
+-------------------------------------------------------------------------------
+-- Message
+-------------------------------------------------------------------------------
+
+-- | A generic IRC message. It consists of a sender prefix, command name
+-- (string or numeric) and optionally a list of parameters.
+data GenericMessage = GenericMessage
+    { gmPrefix  :: Maybe Prefix
+    , gmCommand :: Command
+    , gmParams  :: [Text]
+    }
+    deriving Show
+
+-- | An IRC message of a specific type. This includes only messages whose
+-- command is a name. Messages with a numeric command are handled in the
+-- "Network.IRC.Fun.Messages.Reply" module.
+data SpecificMessage = SpecificMessage (Maybe Prefix) Message deriving Show
+
+-- | Some IRC commands have targets. For example, to which channel to send a
+-- given text message. Targets are specified as parameters in IRC messages.
+data MessageTarget
+    -- | An IRC channel.
+    = ChannelTarget Channel
+    -- | An IRC user. Possible combinations in the protocol are:
+    --
+    -- * Address              (address host is required)
+    -- * Address and server   (address host is optional)
+    -- * Nickname
+    -- * Nickname and address (address host is required)
+    | UserTarget (Maybe Nickname) (Maybe UserAddress) (Maybe Hostname)
+    -- | A mask which matches the server or host of the users to whom the
+    -- message should be sent.
+    | MaskTarget TargetMask
+    deriving Show
+
+-- | A server query. Can be sent through a 'StatsMessage'.
+data Query
+    -- | TODO
+    = Connections
+    -- | TODO
+    | CommandUsage
+    -- | TODO
+    | PrivilegedUsers
+    -- | TODO
+    | Uptime
+    -- | TODO
+    | OtherQuery Char
+    deriving Show
+
+-- TODO in all the either-servername-mask occurences, make sure in the RFC
+-- that they are "<target> may contain wildcards" cases, and replace them with
+-- plain Hostname - let's treat mask as a user mask (for bans etc.)
+-- TODO in all the <target> cases, do they mean a user can be specified too,
+-- to mean "the server this user is connected to"? try with some IRC servers
+-- over telnet, and change Hostname to Target if yes. Note that servername
+-- has '.' chars while a nickname can't, so that's how one tells which is which
+-- Also compare with existing irc packages, how they model these messages
+
+-- | An IRC message of specific type (excluding the optional sender prefix, see
+-- 'SpecificMessage').
+data Message
+-- Connection registration
+    = PassMessage Password
+    | NickMessage Nickname
+    -- | first bool = whether invisible, second bool = whether sees wallops
+    | UserMessage Username Bool Bool RealName
+    | OperMessage Username Password
+    -- | first list: modes to remove (-), second list: modes to add (+)
+    | UserModeMessage Nickname [UserMode] [UserMode]
+    | ServiceMessage Nickname Mask Text
+    | QuitMessage (Maybe Comment)
+    | SQuitMessage Hostname Comment
+-- Channel operations
+    | JoinMessage (Maybe ([Channel], [ChannelKey]))
+    | PartMessage [Channel] (Maybe Comment)
+    -- first: remove (-), second: add/set (+)
+    | ChannelModeMessage [ChannelMode] [ChannelMode]
+    | TopicMessage Channel (Maybe ChannelTopic)
+    | NamesMessage [Channel] (Maybe Hostname)
+    | ListMessage [Channel] (Maybe Hostname)
+    | InviteMessage Nickname Channel
+    | KickMessage [Channel] [Username] (Maybe Comment)
+-- Sending messages
+    | PrivMsgMessage MessageTarget MsgContent
+    | PrivActionMessage MessageTarget MsgContent
+    | NoticeMessage MessageTarget MsgContent
+-- Server queries and commands
+    | MotdMessage (Maybe Hostname)
+    | LusersMessage (Maybe (Mask, Maybe Hostname))
+    | VersionMessage (Maybe (Either Hostname Mask))
+    | StatsMessage (Maybe (Query, Maybe (Either Hostname Mask)))
+    | LinksMessage (Maybe (Maybe (Either Hostname Mask), Mask))
+    | TimeMessage (Maybe (Either Hostname Mask))
+    | ConnectMessage Hostname PortNumber (Either Hostname Mask)
+    | TraceMessage (Maybe Target)
+    | AdminMessage (Maybe Target)
+    | InfoMessage (Maybe Target)
+-- Service query and commands
+    | ServlistMessage (Maybe (Mask, Maybe Text))
+    | SQueryMessage ServiceName MsgContent
+-- User based queries
+    | WhoMessage (Maybe (Mask, Bool))
+    | WhoisMessage (Maybe Hostname) [Mask]
+    | WhowasMessage [Nickname] (Maybe (Int, Maybe Hostname))
+-- Miscellaneous messages
+    | KillMessage Nickname Comment
+    | PingMessage Hostname (Maybe Hostname)
+    | PongMessage Hostname (Maybe Hostname)
+    | ErrorMessage Text
+-- Optional features
+    | AwayMessage (Maybe MsgContent)
+    | RehashMessage
+    | DieMessage
+    | RestartMessage
+    | SummonMessage Username (Maybe (Hostname, Maybe Channel))
+    | UsersMessage (Maybe Hostname)
+    | WallopsMessage MsgContent
+    | UserhostMessage [Nickname]
+    | IsonMessage [Nickname]
+    deriving Show
+
+-------------------------------------------------------------------------------
+-- Modes
+-------------------------------------------------------------------------------
+
+-- | TODO
+data UserMode
+    -- http://toxin.jottit.com/freenode_user_modes
+    = UModeInvisible
+    | UModeCallerID
+    | UModeSeeWallops
+    | UModeDeaf
+    | UModeNoForwarding
+    | UModeBlockUnidentified
+    | UModeConnectedViaSSL
+    -- from the irc rfc, MODE message (section 3.1.5)
+    | UModeAway
+    | UModeRestricted
+    | UModeOperator
+    | UModeLocalOperator
+    | UModeSeeNotices
+    | UModeOther Char
+    deriving (Eq, Show)
+
+-- | TODO
+data ChannelMode
+    = CModeCreator
+    | CModeOperator
+    | CModeVoice
+    | CModeAnonymous
+    | CModeInviteOnly
+    | CModeModerated
+    | CModeNoMessagesFromOutside
+    | CModeQuiet
+    | CModePrivate
+    | CModeSecret
+    | CModeServerReop
+    | CModeTopicSettableByChannelOpOnly
+    | CModeKey (Maybe ChannelKey)
+    | CModeUserLimit (Maybe Int)
+    | CModeBanMask (Maybe Mask)
+    | CModeExceptionMask (Maybe Mask)
+    | CModeInvitationMask (Maybe Mask)
+    | CModeOther Char [Text]
+    | CModeFreenodeQuiet (Maybe Mask)
+    deriving (Eq, Show)
+
+data ChannelModeType
+    = ModeTypeList
+    | ModeTypeSetting
+    | ModeTypeMaybeSetting
+    | ModeTypeFlag
+
+-------------------------------------------------------------------------------
+-- Reply
+-------------------------------------------------------------------------------
+
+-- | TODO
+data CommandResponseCode
+    -- | TODO
+    = ReplyWelcome
+    -- | TODO
+    | ReplyYourHost
+    -- | TODO
+    | ReplyCreated
+    -- | TODO
+    | ReplyMyInfo
+    -- | TODO
+    | ReplyBounce
+    -- | TODO
+    | ReplyUserHost
+    -- | TODO
+    | ReplyIsOn
+    -- | TODO
+    | ReplyAway
+    -- | TODO
+    | ReplyUnAway
+    -- | TODO
+    | ReplyNoAway
+    -- | TODO
+    | ReplyWhoIsUser
+    -- | TODO
+    | ReplyWhoIsServer
+    -- | TODO
+    | ReplyWhoIsOperator
+    -- | TODO
+    | ReplyWhoIsIdle
+    -- | TODO
+    | ReplyEndOfWhoIs
+    -- | TODO
+    | ReplyWhoIsChannels
+    -- | TODO
+    | ReplyWhoWasUser
+    -- | TODO
+    | ReplyEndOfWhoWas
+    -- | TODO
+    | ReplyListStart
+    -- | TODO
+    | ReplyList
+    -- | TODO
+    | ReplyListEnd
+    -- | TODO
+    | ReplyUniqueOpIs
+    -- | TODO
+    | ReplyChannelModeIs
+    -- | TODO
+    | ReplyNoTopic
+    -- | TODO
+    | ReplyTopic
+    -- | TODO
+    | ReplyInviting
+    -- | TODO
+    | ReplySummoning
+    -- | TODO
+    | ReplyInviteList
+    -- | TODO
+    | ReplyEndOfInviteList
+    -- | TODO
+    | ReplyExceptList
+    -- | TODO
+    | ReplyEndOfExceptList
+    -- | TODO
+    | ReplyVersion
+    -- | TODO
+    | ReplyWhoReply
+    -- | TODO
+    | ReplyEndOfWho
+    -- | TODO
+    | ReplyNameReply
+    -- | TODO
+    | ReplyEndOfNames
+    -- | TODO
+    | ReplyLinks
+    -- | TODO
+    | ReplyEndOfLinks
+    -- | TODO
+    | ReplyBanList
+    -- | TODO
+    | ReplyEndOfBanList
+    -- | TODO
+    | ReplyInfo
+    -- | TODO
+    | ReplyEndOfInfo
+    -- | TODO
+    | ReplyMotdStart
+    -- | TODO
+    | ReplyMessageOfTheDay
+    -- | TODO
+    | ReplyEndOfMessageOfTheDay
+    -- | TODO
+    | ReplyYoureOper
+    -- | TODO
+    | ReplyRehashing
+    -- | TODO
+    | ReplyYoureService
+    -- | TODO
+    | ReplyTime
+    -- | TODO
+    | ReplyUsersStart
+    -- | TODO
+    | ReplyUsers
+    -- | TODO
+    | ReplyEndOfUsers
+    -- | TODO
+    | ReplyNoUsers
+    -- | TODO
+    | ReplyTraceLink
+    -- | TODO
+    | ReplyTraceConnecting
+    -- | TODO
+    | ReplyTraceHandshake
+    -- | TODO
+    | ReplyTraceUnknown
+    -- | TODO
+    | ReplyTraceOperator
+    -- | TODO
+    | ReplyTraceUser
+    -- | TODO
+    | ReplyTraceServer
+    -- | TODO
+    | ReplyTraceService
+    -- | TODO
+    | ReplyTraceNewType
+    -- | TODO
+    | ReplyTraceClass
+    -- | TODO
+    | ReplyTraceReconnect
+    -- | TODO
+    | ReplyTraceLog
+    -- | TODO
+    | ReplyTraceEnd
+    -- | TODO
+    | ReplyStatsLinkInfo
+    -- | TODO
+    | ReplyStatsCommands
+    -- | TODO
+    | ReplyEndOfStats
+    -- | TODO
+    | ReplyStatsUptime
+    -- | TODO
+    | ReplyStatsOLine
+    -- | TODO
+    | ReplyUModeIs
+    -- | TODO
+    | ReplyServList
+    -- | TODO
+    | ReplyServListEnd
+    -- | TODO
+    | ReplyLuserClient
+    -- | TODO
+    | ReplyLuserOp
+    -- | TODO
+    | ReplyLuserUnknown
+    -- | TODO
+    | ReplyLuserChannels
+    -- | TODO
+    | ReplyLuserMe
+    -- | TODO
+    | ReplyAdminMe
+    -- | TODO
+    | ReplyAdminLocation1
+    -- | TODO
+    | ReplyAdminLocation2
+    -- | TODO
+    | ReplyAdminEmail
+    -- | TODO
+    | ReplyTryAgain
+    -- | TODO
+    | ReplyFreenodeISupport
+    deriving (Eq, Show)
+
+data ErrorReplyCode
+    -- | TODO
+    = ErrorNoSuchNick
+    -- | TODO
+    | ErrorNoSuchServer
+    -- | TODO
+    | ErrorNoSuchChannel
+    -- | TODO
+    | ErrorCannotSendToChannel
+    -- | TODO
+    | ErrorTooManyChannels
+    -- | TODO
+    | ErrorWasNoSuchNick
+    -- | TODO
+    | ErrorTooManyTargets
+    -- | TODO
+    | ErrorNoSuchService
+    -- | TODO
+    | ErrorNoOrigin
+    -- | TODO
+    | ErrorNoRecipient
+    -- | TODO
+    | ErrorNoTextToSend
+    -- | TODO
+    | ErrorNoTopLevel
+    -- | TODO
+    | ErrorWildTopLevel
+    -- | TODO
+    | ErrorBadMask
+    -- | TODO
+    | ErrorUnknownCommand
+    -- | TODO
+    | ErrorNoMessageOfTheDay
+    -- | TODO
+    | ErrorNoAdminInfo
+    -- | TODO
+    | ErrorFileError
+    -- | TODO
+    | ErrorNoNicknameGiven
+    -- | TODO
+    | ErrorErroneousNickname
+    -- | TODO
+    | ErrorNicknameInUse
+    -- | TODO
+    | ErrorNickCollision
+    -- | TODO
+    | ErrorUnavailableResource
+    -- | TODO
+    | ErrorUserNotInChannel
+    -- | TODO
+    | ErrorNotOnChannel
+    -- | TODO
+    | ErrorUserOnChannel
+    -- | TODO
+    | ErrorNoLogin
+    -- | TODO
+    | ErrorSummonDisabled
+    -- | TODO
+    | ErrorUsersDisabled
+    -- | TODO
+    | ErrorNotRegistered
+    -- | TODO
+    | ErrorNeedMoreParams
+    -- | TODO
+    | ErrorAlreadyRegistered
+    -- | TODO
+    | ErrorNoPermissionForHost
+    -- | TODO
+    | ErrorPasswordMismatch
+    -- | TODO
+    | ErrorYoureBannedCreep
+    -- | TODO
+    | ErrorYouWillBeBanned
+    -- | TODO
+    | ErrorKeySet
+    -- | TODO
+    | ErrorChannelIsFull
+    -- | TODO
+    | ErrorUnknownMode
+    -- | TODO
+    | ErrorInviteOnlyChannel
+    -- | TODO
+    | ErrorBannedFromChannel
+    -- | TODO
+    | ErrorBadChannelKey
+    -- | TODO
+    | ErrorBadChannelMask
+    -- | TODO
+    | ErrorNoChannelModes
+    -- | TODO
+    | ErrorBanListFull
+    -- | TODO
+    | ErrorNoPrivileges
+    -- | TODO
+    | ErrorChannelOpPrivilegesNeeded
+    -- | TODO
+    | ErrorCantKillServer
+    -- | TODO
+    | ErrorRestricted
+    -- | TODO
+    | ErrorUniqueOpPrivilegesNeeded
+    -- | TODO
+    | ErrorNoOperHost
+    -- | TODO
+    | ErrorUModeUnknownFlag
+    -- | TODO
+    | ErrorUsersDontMatch
+    deriving (Eq, Show)
+
+data ReservedReplyCode
+    -- | TODO
+    = ReservedReplyServiceInfo
+    -- | TODO
+    | ReservedReplyEndOfServices
+    -- | TODO
+    | ReservedReplyService
+    -- | TODO
+    | ReservedReplyNone
+    -- | TODO
+    | ReservedReplyWhoIsChannelOp
+    -- | TODO
+    | ReservedReplyKillDone
+    -- | TODO
+    | ReservedReplyClosing
+    -- | TODO
+    | ReservedReplyCloseEnd
+    -- | TODO
+    | ReservedReplyInfoStart
+    -- | TODO
+    | ReservedReplyMyPortIs
+    -- | TODO
+    | ReservedReplyStatsCLine
+    -- | TODO
+    | ReservedReplyStatsNLine
+    -- | TODO
+    | ReservedReplyStatsILine
+    -- | TODO
+    | ReservedReplyStatsKLine
+    -- | TODO
+    | ReservedReplyStatsQLine
+    -- | TODO
+    | ReservedReplyStatsYLine
+    -- | TODO
+    | ReservedReplyStatsVLine
+    -- | TODO
+    | ReservedReplyStatsLLine
+    -- | TODO
+    | ReservedReplyStatsHLine
+    -- | TODO
+    | ReservedReplyStatsSLine
+    -- | TODO
+    | ReservedReplyStatsPing
+    -- | TODO
+    | ReservedReplyStatsBLine
+    -- | TODO
+    | ReservedReplyStatsDLine
+    deriving (Eq, Show)
+
+-- | TODO
+data ReservedErrorCode
+    -- | TODO
+    = ReservedErrorNoServiceHost
+    deriving (Eq, Show)
+
+-- | TODO
+data GenericReply = GenericReply
+    { grSender :: Hostname
+    , grCode   :: CmdNumber
+    , grTarget :: Target
+    , grParams :: [Parameter]
+    }
+    deriving Show
+
+-- | TODO
+data Reply
+    -- | TODO
+    = WelcomeReply
+    -- | TODO
+    | YourHostReply
+    -- | TODO
+    | CreatedReply
+    -- | TODO
+    | MyInfoReply
+    -- | TODO
+    | BounceReply
+    -- | TODO
+    | ISupportReply
+    -- | TODO
+    | UserHostReply
+    -- | TODO
+    | IsOnReply
+    -- | TODO
+    | AwayReply
+    -- | TODO
+    | UnAwayReply
+    -- | TODO
+    | NoAwayReply
+    -- | TODO
+    | WhoIsUserReply
+    -- | TODO
+    | WhoIsServerReply
+    -- | TODO
+    | WhoIsOperatorReply
+    -- | TODO
+    | WhoIsIdleReply
+    -- | TODO
+    | EndOfWhoIsReply
+    -- | TODO
+    | WhoIsChannelsReply
+    -- | TODO
+    | WhoWasUserReply
+    -- | TODO
+    | EndOfWhoWasReply
+    -- | TODO
+    | ListStartReply
+    -- | TODO
+    | ListReply
+    -- | TODO
+    | ListEndReply
+    -- | TODO
+    | UniqueOpIsReply
+    -- | TODO
+    | ChannelModeIsReply
+    -- | TODO
+    | NoTopicReply
+    -- | TODO
+    | TopicReply
+    -- | TODO
+    | InvitingReply
+    -- | TODO
+    | SummoningReply
+    -- | TODO
+    | InviteListReply
+    -- | TODO
+    | EndOfInviteListReply
+    -- | TODO
+    | ExceptListReply
+    -- | TODO
+    | EndOfExceptListReply
+    -- | TODO
+    | VersionReply
+    -- | TODO
+    | WhoReply
+    -- | TODO
+    | EndOfWhoReply
+    -- | Lists members of IRC channels. Sent when JOINing a channel to list the
+    -- users in that channel, or as a response to the NAMES command.
+    | NamesReply ChannelPrivacy Channel [(Privilege, Nickname)]
+    -- | Sent after a sequence of 0 or more 'NameReply's, to signal that the
+    -- list transmission is finished.
+    | EndOfNamesReply
+    -- | TODO
+    | LinksReply
+    -- | TODO
+    | EndOfLinksReply
+    -- | TODO
+    | BanListReply
+    -- | TODO
+    | EndOfBanListReply
+    -- | TODO
+    | InfoReply
+    -- | TODO
+    | EndOfInfoReply
+    -- | TODO
+    | MotdStartReply
+    -- | TODO
+    | MessageOfTheDayReply
+    -- | TODO
+    | EndOfMessageOfTheDayReply
+    -- | TODO
+    | YoureOperReply
+    -- | TODO
+    | RehashingReply
+    -- | TODO
+    | YoureServiceReply
+    -- | TODO
+    | TimeReply
+    -- | TODO
+    | UsersStartReply
+    -- | TODO
+    | UsersReply
+    -- | TODO
+    | EndOfUsersReply
+    -- | TODO
+    | NoUsersReply
+    -- | TODO
+    | TraceLinkReply
+    -- | TODO
+    | TraceConnectingReply
+    -- | TODO
+    | TraceHandshakeReply
+    -- | TODO
+    | TraceUnknownReply
+    -- | TODO
+    | TraceOperatorReply
+    -- | TODO
+    | TraceUserReply
+    -- | TODO
+    | TraceServerReply
+    -- | TODO
+    | TraceServiceReply
+    -- | TODO
+    | TraceNewTypeReply
+    -- | TODO
+    | TraceClassReply
+    -- | TODO
+    | TraceReconnectReply
+    -- | TODO
+    | TraceLogReply
+    -- | TODO
+    | TraceEndReply
+    -- | TODO
+    | StatsLinkInfoReply
+    -- | TODO
+    | StatsCommandsReply
+    -- | TODO
+    | EndOfStatsReply
+    -- | TODO
+    | StatsUptimeReply
+    -- | TODO
+    | StatsOLineReply
+    -- | TODO
+    | UModeIsReply
+    -- | TODO
+    | ServListReply
+    -- | TODO
+    | ServListEndReply
+    -- | TODO
+    | LuserClientReply
+    -- | TODO
+    | LuserOpReply
+    -- | TODO
+    | LuserUnknownReply
+    -- | TODO
+    | LuserChannelsReply
+    -- | TODO
+    | LuserMeReply
+    -- | TODO
+    | AdminMeReply
+    -- | TODO
+    | AdminLocation1Reply
+    -- | TODO
+    | AdminLocation2Reply
+    -- | TODO
+    | AdminEmailReply
+    -- | TODO
+    | TryAgainReply
+    deriving (Eq, Show)
+
+-- | An IRC server numeric reply of a specific type.
+data SpecificReply = SpecificReply Hostname Target Reply deriving Show
+
+-- | Specifies the number of parameter a certain IRC message type accepts.
+data ArgSpec
+    = Exactly Int
+    | AtLeast Int
+    | AtMost Int
+    | Between Int Int
+    | OneOf [Int]
+    deriving (Show)
+
+-- | An error occuring while analyzing a parsed IRC protocol message into a
+-- specific message type, such as 'JoinMessage'.
+data AnalysisError
+    = WrongNumArgs Int (Maybe ArgSpec)
+    | InvalidArg (Maybe Int) (Maybe Text) (Maybe Text)
+    | OtherError Text
+    deriving (Show)
diff --git a/src/Network/Irc/Types/Base.hs b/src/Network/Irc/Types/Base.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Irc/Types/Base.hs
@@ -0,0 +1,98 @@
+{- This file is part of irc-fun-types.
+ -
+ - Written in 2015, 2016 by fr33domlover <fr33domlover@riseup.net>.
+ -
+ - ♡ Copying is an act of love. Please copy, reuse and share.
+ -
+ - The author(s) have dedicated all copyright and related and neighboring
+ - rights to this software to the public domain worldwide. This software is
+ - distributed without any warranty.
+ -
+ - You should have received a copy of the CC0 Public Domain Dedication along
+ - with this software. If not, see
+ - <http://creativecommons.org/publicdomain/zero/1.0/>.
+ -}
+
+-- For deriving trivial no-op instances for newtypes
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+module Network.Irc.Types.Base
+    ( Hostname (..)
+    , ServiceName (..)
+    , Username (..)
+    , Nickname (..)
+    , Channel (..)
+    , CmdName (..)
+    , CmdNumber (..)
+    , Parameter
+    , MsgContent (..)
+    , Password (..)
+    , ChannelKey (..)
+    , ChannelTopic (..)
+    , RealName (..)
+    , Comment (..)
+    , PortNumber (..)
+    , Privilege (..)
+    , ChannelPrivacy (..)
+    )
+where
+
+import Data.Hashable (Hashable)
+import Data.Monoid (Monoid)
+import Data.String (IsString)
+import Data.Text (Text)
+
+-- | IRC server hostname, e.g. @orwell.freenode.net@
+newtype Hostname = Hostname { unHostname :: Text } deriving (Eq, Show)
+
+-- | An IRC service name.
+newtype ServiceName = ServiceName { unServiceName :: Text } deriving (Eq, Show)
+
+-- | System user name, i.e. the first part of user\@host.tld
+newtype Username = Username { unUsername :: Text } deriving (Eq, Show)
+
+-- | IRC nickname
+newtype Nickname = Nickname { unNickname :: Text }
+    deriving (Eq, Show, Hashable)
+
+-- | IRC channel name (including the prefix character), e.g. @#freepost@
+newtype Channel = Channel { unChannel :: Text } deriving (Eq, Show, Hashable)
+
+-- | IRC protocol command name, i.e. @PRIVMSG@
+newtype CmdName = CmdName { unCmdName :: Text } deriving (Eq, Show)
+
+-- | IRC protocol numeric command number
+newtype CmdNumber = CmdNumber { unCmdNumber :: Int } deriving (Eq, Show)
+
+-- | IRC message parameter, e.g. second word in @JOIN #freepost@
+type Parameter = Text
+
+-- | Chat message content, i.e. a message or a part of a text message meant to
+-- be sent or received between people through IRC.
+newtype MsgContent = MsgContent { unMsgContent :: Text }
+    deriving (Show, Monoid, IsString)
+
+-- | IRC connection password.
+newtype Password = Password { unPassword :: Text } deriving (Eq, Show)
+
+-- | IRC channel password.
+newtype ChannelKey = ChannelKey { unChannelKey :: Text } deriving (Eq, Show)
+
+-- | IRC channel topic line.
+newtype ChannelTopic = ChannelTopic { unChannelTopic :: Text } deriving Show
+
+-- | A user's \"real name\" as kept by the IRC server.
+newtype RealName = RealName { unRealName :: Text } deriving Show
+
+-- | An optional comment used by several IRC commands, e.g. a part message,
+-- which is a line shown when a user leaves a channel.
+newtype Comment = Comment { unComment :: Text } deriving Show
+
+-- | Network port number.
+newtype PortNumber = PortNumber { unPortNumber :: Int } deriving (Eq, Show)
+
+-- | IRC privilege status for a user in the context of a specific channel.
+data Privilege = Regular | Voice | Operator deriving (Eq, Show)
+
+-- | IRC channel privacy settings.
+data ChannelPrivacy = Secret | Private | Public deriving (Eq, Show)
