diff --git a/NanoID.cabal b/NanoID.cabal
--- a/NanoID.cabal
+++ b/NanoID.cabal
@@ -1,5 +1,5 @@
 name:                NanoID
-version:             2.1.0
+version:             3.0.0
 synopsis:            NanoID generator
 description:         Library and CLI tool for NanoID generation
 license:             BSD3
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -13,14 +13,17 @@
 main :: IO ()
 main = do
   Options{..} <- execParser opts
-  if length < 1 || quantity < 1
-    then putStrLn "Bad numeric input. See help (-h)." >> exitFailure
-    else do
-      let alphabet' = Alphabet { unAlphabet = C.pack alphabet }
-      replicateM_ quantity $
-        createSystemRandom >>= customNanoID alphabet' (Just length) >>= putNanoID newline
-      exitSuccess
-        where
-          putNanoID nl = either (put nl . C.pack) (put nl . unNanoID)
-            where put nl = if nl then C.putStrLn else C.putStr
+  if length < 1
+    then strFail "nanoid length"
+    else if quantity < 1
+      then strFail "quantity"
+      else do
+        let alphabet' = Alphabet { unAlphabet = C.pack alphabet }
+        replicateM_ quantity $
+          createSystemRandom >>= customNanoID alphabet' (toEnum length) >>= putNanoID newline
+        exitSuccess
+  where
+    strFail m = putStrLn ("Bad " <> m <> ". See help (-h).") >> exitFailure
+    putNanoID nl = put nl . unNanoID
+      where put nl = if nl then C.putStrLn else C.putStr
 
diff --git a/app/Options.hs b/app/Options.hs
--- a/app/Options.hs
+++ b/app/Options.hs
@@ -16,7 +16,7 @@
 opts = info (options <**> helper)
   ( fullDesc
     <> progDesc "NanoID generator"
-    <> header "nanoid v2.1.0, (c) Michel Boucey 2021" )
+    <> header "nanoid v3.0.0, (c) Michel Boucey 2021" )
 
 options :: Parser Options
 options =
diff --git a/src/Data/NanoID.hs b/src/Data/NanoID.hs
--- a/src/Data/NanoID.hs
+++ b/src/Data/NanoID.hs
@@ -3,24 +3,33 @@
 import           Control.Monad
 import qualified Data.ByteString.Char8 as C
 import           Data.Maybe
+import           Numeric.Natural
 import           System.Random.MWC
 
 newtype NanoID = NanoID { unNanoID :: C.ByteString } deriving (Eq, Show)
 
 newtype Alphabet = Alphabet { unAlphabet :: C.ByteString } deriving (Eq, Show)
 
-type Length = Int
+type Length = Natural
 
-nanoID :: IO (Either String NanoID)
-nanoID = createSystemRandom >>= customNanoID defaultAlphabet Nothing
+-- | Standard 'NanoID' generator function
+-- >λ: g <- createSystemRandom
+-- >λ: NanoID g
+-- >NanoID {unNanoID = "x2f8yFadImeVp14ByJ8R3"}
+--
+nanoID :: GenIO -> IO NanoID
+nanoID = customNanoID defaultAlphabet 21
 
-customNanoID :: Alphabet -> Maybe Length -> GenIO-> IO (Either String NanoID)
-customNanoID a l g = do
-  let l' = fromMaybe 21 l
-  when (l' < 1) (fail "Negative length for a NanoID")
-  let ua = unAlphabet a
-      al = C.length ua
-  pure . NanoID . C.pack <$> replicateM l' ((\r -> C.index ua (r-1)) <$> uniformR (1,al) g)
+-- | Customable 'NanoID' generator function
+customNanoID :: Alphabet  -- ^ An 'Alphabet' of your choice
+             -> Length    -- ^ A 'NanoID' length (the standard length is 21 chars)
+             -> GenIO     -- ^ The pseudo-random number generator state
+             -> IO NanoID
+customNanoID a l g =
+  NanoID . C.pack <$> replicateM (fromEnum l) ((\r -> C.index ua (r-1)) <$> uniformR (1,al) g)
+  where
+    ua = unAlphabet a
+    al = C.length ua
 
 -- | The default 'Alphabet', made of URL-friendly symbols.
 defaultAlphabet :: Alphabet
