diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,34 @@
+# 0.4.0.0
+
+- Revised the module structure of the package, replacing the
+  `Data.MonoidMap.Internal` module with the following modules:
+
+  - `Data.MonoidMap.Internal.NonNull`
+  - `Data.MonoidMap.Internal.NonNullMap`
+  - `Data.MonoidMap.Internal.NonNullMap.FromMap`
+  - `Data.MonoidMap.Internal.NonNullMap.FromMapWith`
+
+  The new structure has the following aims:
+
+  - To confine the data constructor of `NonNull` to two small private
+    modules, making the code that maintains the `NonNull` invariant
+    a little easier to audit.
+
+  - To dedicate each public module to a single type, with functions named
+    for qualified import. Several functions have been renamed accordingly:
+    for example, `maybeNonNull` is now `NonNull.nonNull`, and
+    `fromNonNullMap` is now `NonNullMap.toMap`.
+
+  - To move the alternative `fromMap*` and `fromMapWith*` implementations,
+    which exist only for benchmarking, into their own modules, so that
+    they no longer clutter the main API.
+
+- Changed `fromMap`, `fromMapWith`, and `toMap` to accept or return values
+  of type `NonNullMap k v` instead of `Map k (NonNull v)`.
+
+- Added documentation for the `NonNull` and `NonNullMap` types and their
+  functions.
+
 # 0.3.0.0
 
 - Moved the `MonoidMap` type, its instances, and all of its functions to
diff --git a/components/monoidmap-internal-benchmark/Main.hs b/components/monoidmap-internal-benchmark/Main.hs
--- a/components/monoidmap-internal-benchmark/Main.hs
+++ b/components/monoidmap-internal-benchmark/Main.hs
@@ -36,7 +36,9 @@
     ( Benchmark, bcompare, bench, bgroup, defaultMain, nf )
 
 import qualified Data.Map.Strict as OMap
-import qualified Data.MonoidMap.Internal as MMap
+import qualified Data.MonoidMap.Internal.NonNullMap as MMap
+import qualified Data.MonoidMap.Internal.NonNullMap.FromMap as MMap
+import qualified Data.MonoidMap.Internal.NonNullMap.FromMapWith as MMap
 
 main :: IO ()
 main = do
diff --git a/components/monoidmap-internal/Data/MonoidMap/Internal.hs b/components/monoidmap-internal/Data/MonoidMap/Internal.hs
deleted file mode 100644
--- a/components/monoidmap-internal/Data/MonoidMap/Internal.hs
+++ /dev/null
@@ -1,195 +0,0 @@
-{-# LANGUAGE RoleAnnotations #-}
-{- HLINT ignore "Avoid lambda" -}
-{- HLINT ignore "Avoid lambda using `infix`" -}
-{- HLINT ignore "Redundant bracket" -}
-{- HLINT ignore "Use camelCase" -}
-
--- |
--- Copyright: © 2022–2026 Jonathan Knowles
--- License: Apache-2.0
---
--- Provides /internal/ support for the @monoidmap@ package.
---
--- This module defines the 'NonNull' type of values that are not 'C.null',
--- and functions for constructing maps of 'NonNull' values from ordinary maps.
---
-module Data.MonoidMap.Internal
-    (
-    -- * Types
-      NonNull
-    , NonNullMap (..)
-
-    -- * Non-null values
-    , maybeNonNull
-    , applyNonNull
-    , applyNonNull2
-
-    -- * Non-null maps
-    , fromNonNullMap
-
-    -- * Construction
-    , fromMap
-    , fromMapWith
-
-    -- ** Implementations
-    , fromMap_filter
-    , fromMap_filter_if_any_null
-    , fromMap_mapMaybe
-    , fromMapWith_mapMaybe
-    , fromMapWith_map_filter
-    , fromMapWith_map_filter_if_any_null
-    )
-    where
-
-import Prelude
-
-import Control.DeepSeq
-    ( NFData )
-import Data.Bifoldable
-    ( Bifoldable )
-import Data.Coerce
-    ( coerce )
-import Data.Functor.Classes
-    ( Eq1, Eq2, Show1, Show2 )
-import Data.Map.Strict
-    ( Map )
-import Data.Monoid.Null
-    ( MonoidNull )
-import NoThunks.Class
-    ( NoThunks )
-
-import qualified Data.Foldable as F
-import qualified Data.Map.Strict as Map
-import qualified Data.Monoid.Null as C
-
---------------------------------------------------------------------------------
--- Non-null values
---------------------------------------------------------------------------------
-
-newtype NonNull v = UnsafeNonNull v
-    deriving newtype NFData
-
--- Without an explicit type role annotation, the following role would be
--- inferred:
---
---     type role NonNull representational
---
--- However, the validity of a 'NonNull' value depends on a property of its
--- type: its 'mempty' value. A representational role would allow users to
--- coerce between types with the same representation but different 'mempty'
--- values, even without access to the 'NonNull' constructor.
---
--- For example, users could coerce a 'NonNull' ('Sum' 'Int') to a 'NonNull'
--- ('Product' 'Int'), and thereby construct a 'NonNull' value that is 'mempty'.
---
--- So we must instead choose a nominal role.
---
-type role NonNull nominal
-
-maybeNonNull :: MonoidNull v => v -> Maybe (NonNull v)
-maybeNonNull !v
-    | C.null  v = Nothing
-    | otherwise = Just (UnsafeNonNull v)
-{-# INLINE maybeNonNull #-}
-
-applyNonNull :: (v -> a) -> (NonNull v -> a)
-applyNonNull = coerce
-{-# INLINE applyNonNull #-}
-
-applyNonNull2 :: (v1 -> v2 -> a) -> (NonNull v1 -> NonNull v2 -> a)
-applyNonNull2 = coerce
-{-# INLINE applyNonNull2 #-}
-
-fromNonNullMap :: Map k (NonNull v) -> Map k v
-fromNonNullMap = coerce
-{-# INLINE fromNonNullMap #-}
-
--- | /Unsafely/ converts an ordinary map into a map of non-null values.
---
--- This function /expects/ but does /not/ check that no value in the given map
--- is 'C.null'. It must only be applied to maps that satisfy this condition.
---
-unsafeToNonNullMap :: Map k v -> Map k (NonNull v)
-unsafeToNonNullMap = coerce
-{-# INLINE unsafeToNonNullMap #-}
-
---------------------------------------------------------------------------------
--- Non-null maps
---------------------------------------------------------------------------------
-
--- A map of non-null values.
---
--- Types with the same representation as 'NonNullMap' (such as 'MonoidMap')
--- can derive their instances via this type, without needing access to the
--- constructor of 'NonNull'.
---
-newtype NonNullMap k v = NonNullMap (Map k (NonNull v))
-    deriving (Eq, Show, NFData, NoThunks) via Map k v
-    deriving (Eq1, Show1, Foldable) via Map k
-    deriving (Eq2, Show2, Bifoldable) via Map
-
--- Strictly speaking, this type role annotation is redundant, as:
---
--- - The type parameter 'k' already has a nominal role inherited from 'Map'.
--- - The type parameter 'v' already has a nominal role inherited from 'NonNull'.
---
--- But we reassert these roles here, so that they cannot be silently weakened
--- by a future change to the representation of 'NonNullMap'.
---
-type role NonNullMap nominal nominal
-
---------------------------------------------------------------------------------
--- Construction
---------------------------------------------------------------------------------
-
--- | Constructs a map of non-null values from an ordinary 'Map', removing all
---   'C.null' values.
---
--- This function selects which of the @fromMap_*@ implementations below is used
--- by the public @fromMap@ function of the @monoidmap@ package.
---
-fromMap :: MonoidNull v => Map k v -> Map k (NonNull v)
-fromMap = fromMap_filter_if_any_null
-{-# INLINE fromMap #-}
-
-fromMap_filter :: MonoidNull v => Map k v -> Map k (NonNull v)
-fromMap_filter = unsafeToNonNullMap . Map.filter (\(!v) -> not (C.null v))
-{-# INLINABLE fromMap_filter #-}
-
-fromMap_filter_if_any_null :: MonoidNull v => Map k v -> Map k (NonNull v)
-fromMap_filter_if_any_null m
-    | F.any (\(!v) -> C.null v) m =
-        unsafeToNonNullMap $ Map.filter (\(!v) -> not (C.null v)) m
-    | otherwise =
-        unsafeToNonNullMap m
-{-# INLINABLE fromMap_filter_if_any_null #-}
-
-fromMap_mapMaybe :: MonoidNull v => Map k v -> Map k (NonNull v)
-fromMap_mapMaybe = Map.mapMaybe maybeNonNull
-{-# INLINABLE fromMap_mapMaybe #-}
-
--- | Constructs a map of non-null values from an ordinary 'Map', applying the
---   given function to all values, and removing all 'C.null' values.
---
--- This function selects which of the @fromMapWith_*@ implementations below is
--- used by the public @fromMapWith@ function of the @monoidmap@ package.
---
-fromMapWith
-    :: MonoidNull v2 => (v1 -> v2) -> Map k v1 -> Map k (NonNull v2)
-fromMapWith = fromMapWith_mapMaybe
-{-# INLINE fromMapWith #-}
-
-fromMapWith_mapMaybe
-    :: MonoidNull v2 => (v1 -> v2) -> Map k v1 -> Map k (NonNull v2)
-fromMapWith_mapMaybe f = Map.mapMaybe (maybeNonNull . f)
-{-# INLINABLE fromMapWith_mapMaybe #-}
-
-fromMapWith_map_filter
-    :: MonoidNull v2 => (v1 -> v2) -> Map k v1 -> Map k (NonNull v2)
-fromMapWith_map_filter f = fromMap_filter . Map.map f
-{-# INLINABLE fromMapWith_map_filter #-}
-
-fromMapWith_map_filter_if_any_null
-    :: MonoidNull v2 => (v1 -> v2) -> Map k v1 -> Map k (NonNull v2)
-fromMapWith_map_filter_if_any_null f = fromMap_filter_if_any_null . Map.map f
-{-# INLINABLE fromMapWith_map_filter_if_any_null #-}
diff --git a/components/monoidmap-internal/Data/MonoidMap/Internal/NonNull.hs b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNull.hs
new file mode 100644
--- /dev/null
+++ b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNull.hs
@@ -0,0 +1,49 @@
+-- |
+-- Copyright: © 2022–2026 Jonathan Knowles
+-- License: Apache-2.0
+--
+-- Provides the 'NonNull' type and related functions.
+--
+-- This module is intended to be imported qualified:
+--
+-- @
+-- import Data.MonoidMap.Internal.NonNull (NonNull)
+-- import Data.MonoidMap.Internal.NonNull qualified as NonNull
+-- @
+--
+module Data.MonoidMap.Internal.NonNull
+    (
+    -- * Type
+      NonNull
+
+    -- * Construction
+    , nonNull
+
+    -- * Deconstruction
+    , unwrap
+
+    -- * Function application
+    , apply
+    , apply2
+    )
+    where
+
+import Prelude hiding
+    ( null )
+
+import Data.Monoid.Null
+    ( MonoidNull (null) )
+import Data.MonoidMap.Internal.NonNull.Unsafe
+    ( NonNull, nonNull, unwrap )
+
+-- | Applies a function on ordinary values to a 'NonNull' value.
+--
+apply :: (v -> a) -> (NonNull v -> a)
+apply f = f . unwrap
+{-# INLINE apply #-}
+
+-- | Applies a binary function on ordinary values to two 'NonNull' values.
+--
+apply2 :: (v1 -> v2 -> a) -> (NonNull v1 -> NonNull v2 -> a)
+apply2 f v1 v2 = f (unwrap v1) (unwrap v2)
+{-# INLINE apply2 #-}
diff --git a/components/monoidmap-internal/Data/MonoidMap/Internal/NonNull/Unsafe.hs b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNull/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNull/Unsafe.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE RoleAnnotations #-}
+
+-- |
+-- Copyright: © 2022–2026 Jonathan Knowles
+-- License: Apache-2.0
+--
+-- Defines the 'NonNull' type, together with the primitive operations on
+-- 'NonNull' values that need access to its data constructor.
+--
+module Data.MonoidMap.Internal.NonNull.Unsafe
+    ( NonNull (UnsafeNonNull)
+    , nonNull
+    , unwrap
+    )
+    where
+
+import Prelude hiding
+    ( null )
+
+import Control.DeepSeq
+    ( NFData )
+import Data.Monoid.Null
+    ( MonoidNull (null) )
+
+-- | A value that is not 'null'.
+--
+newtype NonNull v = UnsafeNonNull v
+    deriving newtype NFData
+
+-- Without an explicit type role annotation, the following role would be
+-- inferred:
+--
+--     type role NonNull representational
+--
+-- However, the validity of a 'NonNull' value depends on a property of its
+-- type: its 'mempty' value. A representational role would allow users to
+-- coerce between types with the same representation but different 'mempty'
+-- values, even without access to the 'NonNull' constructor.
+--
+-- For example, users could coerce a 'NonNull' ('Sum' 'Int') to a 'NonNull'
+-- ('Product' 'Int'), and thereby construct a 'NonNull' value that is 'mempty'.
+--
+-- So we must instead choose a nominal role.
+--
+type role NonNull nominal
+
+-- | Converts a value into a 'NonNull' value, returning 'Nothing' if the
+--   value is 'null'.
+--
+nonNull :: MonoidNull v => v -> Maybe (NonNull v)
+nonNull !v
+    | null v    = Nothing
+    | otherwise = Just (UnsafeNonNull v)
+{-# INLINE nonNull #-}
+
+-- | Extracts the value from a 'NonNull' value.
+--
+unwrap :: NonNull v -> v
+unwrap (UnsafeNonNull v) = v
+{-# INLINE unwrap #-}
diff --git a/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap.hs b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap.hs
new file mode 100644
--- /dev/null
+++ b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap.hs
@@ -0,0 +1,68 @@
+-- |
+-- Copyright: © 2022–2026 Jonathan Knowles
+-- License: Apache-2.0
+--
+-- Provides the 'NonNullMap' type and related functions.
+--
+-- This module is intended to be imported qualified:
+--
+-- @
+-- import Data.MonoidMap.Internal.NonNullMap (NonNullMap (..))
+-- import Data.MonoidMap.Internal.NonNullMap qualified as NonNullMap
+-- @
+--
+module Data.MonoidMap.Internal.NonNullMap
+    (
+    -- * Type
+      NonNullMap (..)
+
+    -- * Construction
+    , fromMap
+    , fromMapWith
+
+    -- * Deconstruction
+    , toMap
+    )
+    where
+
+import Prelude hiding
+    ( null )
+
+import Data.Map.Strict
+    ( Map )
+import Data.Monoid.Null
+    ( MonoidNull (null) )
+import Data.MonoidMap.Internal.NonNull
+    ( NonNull )
+import Data.MonoidMap.Internal.NonNullMap.FromMap
+    ( fromMap_filter_if_any_null )
+import Data.MonoidMap.Internal.NonNullMap.FromMapWith
+    ( fromMapWith_mapMaybe )
+import Data.MonoidMap.Internal.NonNullMap.Unsafe
+    ( NonNullMap (..), toMap )
+
+--------------------------------------------------------------------------------
+-- Construction
+--------------------------------------------------------------------------------
+
+-- | Constructs a 'NonNullMap' from an ordinary 'Map', removing all
+--   'null' values.
+--
+-- This function selects which of the implementations in
+-- "Data.MonoidMap.Internal.NonNullMap.FromMap" is used by the public @fromMap@
+-- function of the @monoidmap@ package.
+--
+fromMap :: MonoidNull v => Map k v -> NonNullMap k v
+fromMap = fromMap_filter_if_any_null
+{-# INLINE fromMap #-}
+
+-- | Constructs a 'NonNullMap' from an ordinary 'Map', applying the given
+--   function to all values, and removing all 'null' values.
+--
+-- This function selects which of the implementations in
+-- "Data.MonoidMap.Internal.NonNullMap.FromMapWith" is used by the public
+-- @fromMapWith@ function of the @monoidmap@ package.
+--
+fromMapWith :: MonoidNull v2 => (v1 -> v2) -> Map k v1 -> NonNullMap k v2
+fromMapWith = fromMapWith_mapMaybe
+{-# INLINE fromMapWith #-}
diff --git a/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/FromMap.hs b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/FromMap.hs
new file mode 100644
--- /dev/null
+++ b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/FromMap.hs
@@ -0,0 +1,57 @@
+{- HLINT ignore "Avoid lambda" -}
+{- HLINT ignore "Avoid lambda using `infix`" -}
+{- HLINT ignore "Redundant bracket" -}
+{- HLINT ignore "Use camelCase" -}
+
+-- |
+-- Copyright: © 2022–2026 Jonathan Knowles
+-- License: Apache-2.0
+--
+-- Provides alternative implementations of @fromMap@, which constructs a
+-- map of 'NonNull' values from an ordinary map.
+--
+-- These implementations are exported so that they can be benchmarked against
+-- one another.
+--
+module Data.MonoidMap.Internal.NonNullMap.FromMap
+    ( fromMap_filter
+    , fromMap_filter_if_any_null
+    , fromMap_mapMaybe
+    )
+    where
+
+import Prelude hiding
+    ( null )
+
+import Data.Map.Strict
+    ( Map )
+import Data.Monoid.Null
+    ( MonoidNull (null) )
+import Data.MonoidMap.Internal.NonNull
+    ( NonNull, nonNull )
+import Data.MonoidMap.Internal.NonNullMap.Unsafe
+    ( NonNullMap (..)
+    , unsafeFromMap
+    )
+
+import qualified Data.Foldable as F
+import qualified Data.Map.Strict as Map
+
+fromMap_filter
+    :: MonoidNull v => Map k v -> NonNullMap k v
+fromMap_filter = unsafeFromMap . Map.filter (\(!v) -> not (null v))
+{-# INLINABLE fromMap_filter #-}
+
+fromMap_filter_if_any_null
+    :: MonoidNull v => Map k v -> NonNullMap k v
+fromMap_filter_if_any_null m
+    | F.any (\(!v) -> null v) m =
+        unsafeFromMap $ Map.filter (\(!v) -> not (null v)) m
+    | otherwise =
+        unsafeFromMap m
+{-# INLINABLE fromMap_filter_if_any_null #-}
+
+fromMap_mapMaybe
+    :: MonoidNull v => Map k v -> NonNullMap k v
+fromMap_mapMaybe = NonNullMap . Map.mapMaybe nonNull
+{-# INLINABLE fromMap_mapMaybe #-}
diff --git a/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/FromMapWith.hs b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/FromMapWith.hs
new file mode 100644
--- /dev/null
+++ b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/FromMapWith.hs
@@ -0,0 +1,51 @@
+{- HLINT ignore "Use camelCase" -}
+
+-- |
+-- Copyright: © 2022–2026 Jonathan Knowles
+-- License: Apache-2.0
+--
+-- Provides alternative implementations of @fromMapWith@, which constructs a
+-- map of 'NonNull' values from an ordinary map, applying a function to all
+-- values.
+--
+-- These implementations are exported so that they can be benchmarked against
+-- one another.
+--
+module Data.MonoidMap.Internal.NonNullMap.FromMapWith
+    ( fromMapWith_mapMaybe
+    , fromMapWith_map_filter
+    , fromMapWith_map_filter_if_any_null
+    )
+    where
+
+import Prelude
+
+import Data.Map.Strict
+    ( Map )
+import Data.Monoid.Null
+    ( MonoidNull )
+import Data.MonoidMap.Internal.NonNull
+    ( NonNull, nonNull )
+import Data.MonoidMap.Internal.NonNullMap.FromMap
+    ( fromMap_filter
+    , fromMap_filter_if_any_null
+    )
+import Data.MonoidMap.Internal.NonNullMap.Unsafe
+    ( NonNullMap (..) )
+
+import qualified Data.Map.Strict as Map
+
+fromMapWith_mapMaybe
+    :: MonoidNull v2 => (v1 -> v2) -> Map k v1 -> NonNullMap k v2
+fromMapWith_mapMaybe f = NonNullMap . Map.mapMaybe (nonNull . f)
+{-# INLINABLE fromMapWith_mapMaybe #-}
+
+fromMapWith_map_filter
+    :: MonoidNull v2 => (v1 -> v2) -> Map k v1 -> NonNullMap k v2
+fromMapWith_map_filter f = fromMap_filter . Map.map f
+{-# INLINABLE fromMapWith_map_filter #-}
+
+fromMapWith_map_filter_if_any_null
+    :: MonoidNull v2 => (v1 -> v2) -> Map k v1 -> NonNullMap k v2
+fromMapWith_map_filter_if_any_null f = fromMap_filter_if_any_null . Map.map f
+{-# INLINABLE fromMapWith_map_filter_if_any_null #-}
diff --git a/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/Unsafe.hs b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/components/monoidmap-internal/Data/MonoidMap/Internal/NonNullMap/Unsafe.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE RoleAnnotations #-}
+
+-- |
+-- Copyright: © 2022–2026 Jonathan Knowles
+-- License: Apache-2.0
+--
+-- Defines the 'NonNullMap' type, together with the primitive operations on
+-- 'NonNullMap' that need access to the data constructor of 'NonNull'.
+--
+module Data.MonoidMap.Internal.NonNullMap.Unsafe
+    ( NonNullMap (..)
+    , toMap
+    , unsafeFromMap
+    )
+    where
+
+import Prelude
+
+import Control.DeepSeq
+    ( NFData )
+import Data.Bifoldable
+    ( Bifoldable )
+import Data.Coerce
+    ( coerce )
+import Data.Functor.Classes
+    ( Eq1, Eq2, Show1, Show2 )
+import Data.Map.Strict
+    ( Map )
+import Data.MonoidMap.Internal.NonNull.Unsafe
+    ( NonNull (UnsafeNonNull) )
+import NoThunks.Class
+    ( NoThunks )
+
+-- | A map of 'NonNull' values.
+--
+-- Other types with the same representation (such as @MonoidMap@ from the
+-- @monoidmap@ package) can derive instances via this type, without access
+-- to the data constructor of 'NonNull'.
+--
+newtype NonNullMap k v = NonNullMap (Map k (NonNull v))
+    --
+    -- Here we take great care to only derive instances that consume values.
+    --
+    -- It's risky to derive an instance that produces values, as the derived
+    -- instance may not necessarily respect the 'NonNull' invariant.
+    --
+    -- For example, the 'Read' instance for 'Map', given appropriate input,
+    -- will quite happily produce maps with 'mempty' values.
+    --
+    deriving (Eq, Show, NFData, NoThunks) via Map k v
+    deriving (Eq1, Show1, Foldable) via Map k
+    deriving (Eq2, Show2, Bifoldable) via Map
+
+-- Strictly speaking, this type role annotation is redundant, as:
+--
+-- - The type parameter 'k' already has a nominal role inherited from 'Map'.
+-- - The type parameter 'v' already has a nominal role inherited from 'NonNull'.
+--
+-- But we reassert these roles here, so that they cannot be silently weakened
+-- by a future change to the representation of 'NonNullMap'.
+--
+type role NonNullMap nominal nominal
+
+-- | Converts a 'NonNullMap' into an ordinary map.
+--
+toMap :: NonNullMap k v -> Map k v
+toMap = coerce
+{-# INLINE toMap #-}
+
+-- | /Unsafely/ converts an ordinary map into a 'NonNullMap'.
+--
+-- This function /expects/ but does /not/ check that no value in the given map
+-- is null. It must only be applied to maps that satisfy this condition.
+--
+unsafeFromMap :: Map k v -> NonNullMap k v
+unsafeFromMap = coerce
+{-# INLINE unsafeFromMap #-}
diff --git a/monoidmap-internal.cabal b/monoidmap-internal.cabal
--- a/monoidmap-internal.cabal
+++ b/monoidmap-internal.cabal
@@ -1,6 +1,6 @@
 cabal-version:  3.0
 name:           monoidmap-internal
-version:        0.3.0.0
+version:        0.4.0.0
 homepage:       https://github.com/jonathanknowles/monoidmap/tree/HEAD/packages/monoidmap-internal
 bug-reports:    https://github.com/jonathanknowles/monoidmap/issues
 license:        Apache-2.0
@@ -65,7 +65,13 @@
     hs-source-dirs:
         components/monoidmap-internal
     exposed-modules:
-        Data.MonoidMap.Internal
+        Data.MonoidMap.Internal.NonNull
+        Data.MonoidMap.Internal.NonNullMap
+        Data.MonoidMap.Internal.NonNullMap.FromMap
+        Data.MonoidMap.Internal.NonNullMap.FromMapWith
+    other-modules:
+        Data.MonoidMap.Internal.NonNull.Unsafe
+        Data.MonoidMap.Internal.NonNullMap.Unsafe
     default-language:
         Haskell2010
 
