+-- | A type-safe wrapper around a domain name (represented as a
+-- string) that ensures we've created it by calling
+-- 'normalize_string'. This prevents us from making
+-- comparisons on un-normalized 'Domain's or 'String's.
+--
+newtype NormalDomain =
+ NormalDomain String
+ deriving ( Eq, Ord, Show )
+
+
+-- | A set of mail exchanger names, represented as 'String's. The use
+-- of 'NormalDomain' prevents us from constructing a set of names
+-- that aren't normalized first.
+--
+type MxSet = Set NormalDomain
+
+
+-- | A map from domain names (represented as 'String's) to sets of
+-- mail exchanger names (also represented as 'String's). The use of
+-- 'NormalDomain' in the key prevents us from using keys that aren't
+-- normalized; this is important because we'll be using them for
+-- lookups and want e.g. \"foo.com\" and \"FOO.com\" to look up the
+-- same MX records.
+--
+type MxSetMap = Map NormalDomain MxSet
+
+
+-- | Normalize a domain name string by converting to a 'Domain',
+-- calling 'normalize', and then converting back.
+--
+-- ==== __Examples__
+--
+-- >>> normalize_string "ExAMplE.com"
+-- NormalDomain "example.com."
+--
+normalize_string :: String -> NormalDomain
+normalize_string = NormalDomain . BS.unpack . normalize . BS.pack
+
+
+-- | Retrieve all MX records for the given domain. This is somewhat
+-- inefficient, since we create the resolver every time.
+--