diff --git a/src/lib/Witch.hs b/src/lib/Witch.hs
--- a/src/lib/Witch.hs
+++ b/src/lib/Witch.hs
@@ -140,6 +140,8 @@
   , Witch.Utility.as
   , Witch.Utility.over
   , Witch.Utility.via
+  , Witch.Utility.maybeTryCast
+  , Witch.Utility.eitherTryCast
   , Witch.Utility.tryVia
 
   -- ** Unsafe
@@ -148,6 +150,12 @@
   , Witch.Utility.unsafeInto
 
   -- ** Template Haskell
+  -- | This library uses /typed/ Template Haskell, which may be a little
+  -- different than what you're used to. Normally Template Haskell uses the
+  -- @$(...)@ syntax for splicing in things to run at compile time. The typed
+  -- variant uses the @$$(...)@ syntax for splices, doubling up on the dollar
+  -- signs. Other than that, using typed Template Haskell should be pretty
+  -- much the same as using regular Template Haskell.
   , Witch.Lift.liftedCast
   , Witch.Lift.liftedFrom
   , Witch.Lift.liftedInto
diff --git a/src/lib/Witch/Instances.hs b/src/lib/Witch/Instances.hs
--- a/src/lib/Witch/Instances.hs
+++ b/src/lib/Witch/Instances.hs
@@ -7,6 +7,7 @@
 
 module Witch.Instances where
 
+import qualified Control.Exception as Exception
 import qualified Data.Bits as Bits
 import qualified Data.ByteString as ByteString
 import qualified Data.ByteString.Lazy as LazyByteString
@@ -26,6 +27,7 @@
 import qualified Data.Text.Encoding as Text
 import qualified Data.Text.Lazy as LazyText
 import qualified Data.Text.Lazy.Encoding as LazyText
+import qualified Data.Typeable as Typeable
 import qualified Data.Word as Word
 import qualified Numeric.Natural as Natural
 import qualified Witch.Cast as Cast
@@ -57,27 +59,27 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int8 Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int8 Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int8 Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int8 Word.Word64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int8 Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
--- | Uses 'fromIntegral' when the input is non-negative.
+-- | Uses 'fromIntegral' when the input is not negative.
 instance TryCast.TryCast Int.Int8 Natural.Natural where
-  tryCast = maybeTryCast fromNonNegativeIntegral
+  tryCast = Utility.eitherTryCast fromNonNegativeIntegral
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Int.Int8 Float where
@@ -91,7 +93,7 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int16 Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Int.Int16 Int.Int32 where
@@ -111,27 +113,27 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int16 Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int16 Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int16 Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int16 Word.Word64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int16 Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
--- | Uses 'fromIntegral' when the input is non-negative.
+-- | Uses 'fromIntegral' when the input is not negative.
 instance TryCast.TryCast Int.Int16 Natural.Natural where
-  tryCast = maybeTryCast fromNonNegativeIntegral
+  tryCast = Utility.eitherTryCast fromNonNegativeIntegral
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Int.Int16 Float where
@@ -145,11 +147,11 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int32 Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int32 Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Int.Int32 Int.Int64 where
@@ -157,7 +159,7 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int32 Int where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Int.Int32 Integer where
@@ -165,34 +167,36 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int32 Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int32 Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int32 Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int32 Word.Word64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int32 Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
--- | Uses 'fromIntegral' when the input is non-negative.
+-- | Uses 'fromIntegral' when the input is not negative.
 instance TryCast.TryCast Int.Int32 Natural.Natural where
-  tryCast = maybeTryCast fromNonNegativeIntegral
+  tryCast = Utility.eitherTryCast fromNonNegativeIntegral
 
 -- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215
 -- inclusive.
 instance TryCast.TryCast Int.Int32 Float where
-  tryCast = maybeTryCast $ \s -> if -maxFloat <= s && s <= maxFloat
-    then Just $ fromIntegral s
-    else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if s < -maxFloat
+    then Left Exception.Underflow
+    else if s > maxFloat
+      then Left Exception.Overflow
+      else Right $ fromIntegral s
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Int.Int32 Double where
@@ -202,19 +206,19 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Int.Int32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Int where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Int.Int64 Integer where
@@ -222,55 +226,59 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Word.Word64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int.Int64 Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
--- | Uses 'fromIntegral' when the input is non-negative.
+-- | Uses 'fromIntegral' when the input is not negative.
 instance TryCast.TryCast Int.Int64 Natural.Natural where
-  tryCast = maybeTryCast fromNonNegativeIntegral
+  tryCast = Utility.eitherTryCast fromNonNegativeIntegral
 
 -- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215
 -- inclusive.
 instance TryCast.TryCast Int.Int64 Float where
-  tryCast = maybeTryCast $ \s -> if -maxFloat <= s && s <= maxFloat
-    then Just $ fromIntegral s
-    else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if s < -maxFloat
+    then Left Exception.Underflow
+    else if s > maxFloat
+      then Left Exception.Overflow
+      else Right $ fromIntegral s
 
 -- | Uses 'fromIntegral' when the input is between -9,007,199,254,740,991 and
 -- 9,007,199,254,740,991 inclusive.
 instance TryCast.TryCast Int.Int64 Double where
-  tryCast = maybeTryCast $ \s -> if -maxDouble <= s && s <= maxDouble
-    then Just $ fromIntegral s
-    else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if s < -maxDouble
+    then Left Exception.Underflow
+    else if s > maxDouble
+      then Left Exception.Overflow
+      else Right $ fromIntegral s
 
 -- Int
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int Int.Int32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Int Int.Int64 where
@@ -282,108 +290,117 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int Word.Word64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Int Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
--- | Uses 'fromIntegral' when the input is non-negative.
+-- | Uses 'fromIntegral' when the input is not negative.
 instance TryCast.TryCast Int Natural.Natural where
-  tryCast = maybeTryCast fromNonNegativeIntegral
+  tryCast = Utility.eitherTryCast fromNonNegativeIntegral
 
 -- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215
 -- inclusive.
 instance TryCast.TryCast Int Float where
-  tryCast = maybeTryCast $ \s -> if -maxFloat <= s && s <= maxFloat
-    then Just $ fromIntegral s
-    else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if s < -maxFloat
+    then Left Exception.Underflow
+    else if s > maxFloat
+      then Left Exception.Overflow
+      else Right $ fromIntegral s
 
 -- | Uses 'fromIntegral' when the input is between -9,007,199,254,740,991 and
 -- 9,007,199,254,740,991 inclusive.
 instance TryCast.TryCast Int Double where
-  tryCast = maybeTryCast $ \s ->
-    if (toInteger (maxBound :: Int) <= maxDouble)
-        || (-maxDouble <= s && s <= maxDouble)
-      then Just $ fromIntegral s
-      else Nothing
+  tryCast = Utility.eitherTryCast $ \s ->
+    if toInteger (maxBound :: Int) <= maxDouble
+      then Right $ fromIntegral s
+      else if s < -maxDouble
+        then Left Exception.Underflow
+        else if s > maxDouble
+          then Left Exception.Overflow
+          else Right $ fromIntegral s
 
 -- Integer
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Int.Int32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Int.Int64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Int where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Word.Word64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Integer Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
--- | Uses 'fromInteger' when the input is non-negative.
+-- | Uses 'fromInteger' when the input is not negative.
 instance TryCast.TryCast Integer Natural.Natural where
-  -- This should use @maybeTryCast fromNonNegativeIntegral@, but that causes a
-  -- bug in GHC 9.0.1. By inlining @fromNonNegativeIntegral@ and replacing
+  -- This should use @eitherTryCast fromNonNegativeIntegral@, but that causes
+  -- a bug in GHC 9.0.1. By inlining @fromNonNegativeIntegral@ and replacing
   -- @fromIntegral@ with @fromInteger@, we can work around the bug.
   -- https://mail.haskell.org/pipermail/haskell-cafe/2021-March/133540.html
-  tryCast =
-    maybeTryCast $ \s -> if s < 0 then Nothing else Just $ fromInteger s
+  tryCast = Utility.eitherTryCast
+    $ \s -> if s < 0 then Left Exception.Underflow else Right $ fromInteger s
 
 -- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215
 -- inclusive.
 instance TryCast.TryCast Integer Float where
-  tryCast = maybeTryCast $ \s -> if -maxFloat <= s && s <= maxFloat
-    then Just $ fromIntegral s
-    else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if s < -maxFloat
+    then Left Exception.Underflow
+    else if s > maxFloat
+      then Left Exception.Overflow
+      else Right $ fromIntegral s
 
 -- | Uses 'fromIntegral' when the input is between -9,007,199,254,740,991 and
 -- 9,007,199,254,740,991 inclusive.
 instance TryCast.TryCast Integer Double where
-  tryCast = maybeTryCast $ \s -> if -maxDouble <= s && s <= maxDouble
-    then Just $ fromIntegral s
-    else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if s < -maxDouble
+    then Left Exception.Underflow
+    else if s > maxDouble
+      then Left Exception.Overflow
+      else Right $ fromIntegral s
 
 -- Word8
 
@@ -409,7 +426,7 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word8 Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word8 Int.Int16 where
@@ -443,7 +460,7 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word16 Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word16 Word.Word32 where
@@ -463,11 +480,11 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word16 Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word16 Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word16 Int.Int32 where
@@ -497,11 +514,11 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word32 Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word32 Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word32 Word.Word64 where
@@ -509,7 +526,7 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word32 Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word32 Natural.Natural where
@@ -517,15 +534,15 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word32 Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word32 Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word32 Int.Int32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word32 Int.Int64 where
@@ -533,17 +550,16 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word32 Int where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word32 Integer where
   cast = fromIntegral
 
--- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215
--- inclusive.
+-- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.
 instance TryCast.TryCast Word.Word32 Float where
-  tryCast = maybeTryCast
-    $ \s -> if s <= maxFloat then Just $ fromIntegral s else Nothing
+  tryCast = Utility.eitherTryCast $ \s ->
+    if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word32 Double where
@@ -553,19 +569,19 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word64 Natural.Natural where
@@ -573,53 +589,53 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Int.Int32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Int.Int64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word.Word64 Int where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word.Word64 Integer where
   cast = fromIntegral
 
--- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215
--- inclusive.
+-- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.
 instance TryCast.TryCast Word.Word64 Float where
-  tryCast = maybeTryCast
-    $ \s -> if s <= maxFloat then Just $ fromIntegral s else Nothing
+  tryCast = Utility.eitherTryCast $ \s ->
+    if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow
 
--- | Uses 'fromIntegral' when the input is between -9,007,199,254,740,991 and
--- 9,007,199,254,740,991 inclusive.
+-- | Uses 'fromIntegral' when the input is less than or equal to
+-- 9,007,199,254,740,991.
 instance TryCast.TryCast Word.Word64 Double where
-  tryCast = maybeTryCast
-    $ \s -> if s <= maxDouble then Just $ fromIntegral s else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if s <= maxDouble
+    then Right $ fromIntegral s
+    else Left Exception.Overflow
 
 -- Word
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word Word.Word64 where
@@ -631,99 +647,98 @@
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word Int.Int32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word Int.Int64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Word Int where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Word Integer where
   cast = fromIntegral
 
--- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215
--- inclusive.
+-- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.
 instance TryCast.TryCast Word Float where
-  tryCast = maybeTryCast
-    $ \s -> if s <= maxFloat then Just $ fromIntegral s else Nothing
+  tryCast = Utility.eitherTryCast $ \s ->
+    if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow
 
--- | Uses 'fromIntegral' when the input is between -9,007,199,254,740,991 and
--- 9,007,199,254,740,991 inclusive.
+-- | Uses 'fromIntegral' when the input is less than or equal to
+-- 9,007,199,254,740,991.
 instance TryCast.TryCast Word Double where
-  tryCast = maybeTryCast $ \s ->
+  tryCast = Utility.eitherTryCast $ \s ->
     if (toInteger (maxBound :: Word) <= maxDouble) || (s <= maxDouble)
-      then Just $ fromIntegral s
-      else Nothing
+      then Right $ fromIntegral s
+      else Left Exception.Overflow
 
 -- Natural
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Word.Word8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Word.Word16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Word.Word32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Word.Word64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Word where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Int.Int8 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Int.Int16 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Int.Int32 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Int.Int64 where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'Bits.toIntegralSized'.
 instance TryCast.TryCast Natural.Natural Int where
-  tryCast = maybeTryCast Bits.toIntegralSized
+  tryCast = Utility.maybeTryCast Bits.toIntegralSized
 
 -- | Uses 'fromIntegral'.
 instance Cast.Cast Natural.Natural Integer where
   cast = fromIntegral
 
--- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215
--- inclusive.
+-- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.
 instance TryCast.TryCast Natural.Natural Float where
-  tryCast = maybeTryCast
-    $ \s -> if s <= maxFloat then Just $ fromIntegral s else Nothing
+  tryCast = Utility.eitherTryCast $ \s ->
+    if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow
 
--- | Uses 'fromIntegral' when the input is between -9,007,199,254,740,991 and
--- 9,007,199,254,740,991 inclusive.
+-- | Uses 'fromIntegral' when the input is less than or equal to
+-- 9,007,199,254,740,991.
 instance TryCast.TryCast Natural.Natural Double where
-  tryCast = maybeTryCast
-    $ \s -> if s <= maxDouble then Just $ fromIntegral s else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if s <= maxDouble
+    then Right $ fromIntegral s
+    else Left Exception.Overflow
 
 -- Float
 
@@ -750,11 +765,12 @@
 -- | Converts via 'Rational' when the input is between -16,777,215 and
 -- 16,777,215 inclusive.
 instance TryCast.TryCast Float Integer where
-  tryCast s = case Utility.tryVia @Rational s of
-    Left e -> Left e
-    Right t -> if -maxFloat <= t && t <= maxFloat
-      then Right t
-      else Left $ TryCastException.TryCastException s
+  tryCast = Utility.eitherTryCast $ \s -> case Utility.tryVia @Rational s of
+    Left e -> Left $ Exception.toException e
+    Right t
+      | t < -maxFloat -> Left $ Exception.toException Exception.Underflow
+      | t > maxFloat -> Left $ Exception.toException Exception.Overflow
+      | otherwise -> Right t
 
 -- | Converts via 'Integer'.
 instance TryCast.TryCast Float Word.Word8 where
@@ -782,8 +798,11 @@
 
 -- | Uses 'toRational' when the input is not NaN or infinity.
 instance TryCast.TryCast Float Rational where
-  tryCast = maybeTryCast
-    $ \s -> if isNaN s || isInfinite s then Nothing else Just $ toRational s
+  tryCast = Utility.eitherTryCast $ \s -> if isNaN s
+    then Left Exception.LossOfPrecision
+    else if isInfinite s
+      then if s > 0 then Left Exception.Overflow else Left Exception.Underflow
+      else Right $ toRational s
 
 -- | Uses 'realToFrac'.
 instance Cast.Cast Float Double where
@@ -814,11 +833,12 @@
 -- | Converts via 'Rational' when the input is between -9,007,199,254,740,991
 -- and 9,007,199,254,740,991 inclusive.
 instance TryCast.TryCast Double Integer where
-  tryCast s = case Utility.tryVia @Rational s of
-    Left e -> Left e
-    Right t -> if -maxDouble <= t && t <= maxDouble
-      then Right t
-      else Left $ TryCastException.TryCastException s
+  tryCast = Utility.eitherTryCast $ \s -> case Utility.tryVia @Rational s of
+    Left e -> Left $ Exception.toException e
+    Right t
+      | t < -maxDouble -> Left $ Exception.toException Exception.Underflow
+      | t > maxDouble -> Left $ Exception.toException Exception.Overflow
+      | otherwise -> Right t
 
 -- | Converts via 'Integer'.
 instance TryCast.TryCast Double Word.Word8 where
@@ -846,8 +866,11 @@
 
 -- | Uses 'toRational' when the input is not NaN or infinity.
 instance TryCast.TryCast Double Rational where
-  tryCast = maybeTryCast
-    $ \s -> if isNaN s || isInfinite s then Nothing else Just $ toRational s
+  tryCast = Utility.eitherTryCast $ \s -> if isNaN s
+    then Left Exception.LossOfPrecision
+    else if isInfinite s
+      then if s > 0 then Left Exception.Overflow else Left Exception.Underflow
+      else Right $ toRational s
 
 -- | Uses 'realToFrac'. This necessarily loses some precision.
 instance Cast.Cast Double Float where
@@ -861,8 +884,9 @@
 
 -- | Uses 'Ratio.numerator' when the denominator is 1.
 instance (Eq a, Num a) => TryCast.TryCast (Ratio.Ratio a) a where
-  tryCast = maybeTryCast $ \s ->
-    if Ratio.denominator s == 1 then Just $ Ratio.numerator s else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if Ratio.denominator s == 1
+    then Right $ Ratio.numerator s
+    else Left Exception.LossOfPrecision
 
 -- | Uses 'fromRational'. This necessarily loses some precision.
 instance Cast.Cast Rational Float where
@@ -892,14 +916,15 @@
 
 -- | Uses 'Complex.realPart' when the imaginary part is 0.
 instance (Eq a, Num a) => TryCast.TryCast (Complex.Complex a) a where
-  tryCast = maybeTryCast $ \s ->
-    if Complex.imagPart s == 0 then Just $ Complex.realPart s else Nothing
+  tryCast = Utility.eitherTryCast $ \s -> if Complex.imagPart s == 0
+    then Right $ Complex.realPart s
+    else Left Exception.LossOfPrecision
 
 -- NonEmpty
 
 -- | Uses 'NonEmpty.nonEmpty'.
 instance TryCast.TryCast [a] (NonEmpty.NonEmpty a) where
-  tryCast = maybeTryCast NonEmpty.nonEmpty
+  tryCast = Utility.maybeTryCast NonEmpty.nonEmpty
 
 -- | Uses 'NonEmpty.toList'.
 instance Cast.Cast (NonEmpty.NonEmpty a) [a] where
@@ -977,9 +1002,7 @@
 
 -- | Uses 'Text.decodeUtf8''.
 instance TryCast.TryCast ByteString.ByteString Text.Text where
-  tryCast s = case Text.decodeUtf8' s of
-    Left _ -> Left $ TryCastException.TryCastException s
-    Right t -> Right t
+  tryCast = Utility.eitherTryCast Text.decodeUtf8'
 
 -- LazyByteString
 
@@ -997,9 +1020,7 @@
 
 -- | Uses 'LazyText.decodeUtf8''.
 instance TryCast.TryCast LazyByteString.ByteString LazyText.Text where
-  tryCast s = case LazyText.decodeUtf8' s of
-    Left _ -> Left $ TryCastException.TryCastException s
-    Right t -> Right t
+  tryCast = Utility.eitherTryCast LazyText.decodeUtf8'
 
 -- ShortByteString
 
@@ -1053,16 +1074,35 @@
 instance Cast.Cast LazyText.Text LazyByteString.ByteString where
   cast = LazyText.encodeUtf8
 
+-- TryCastException
+
 instance Cast.Cast (TryCastException.TryCastException s t0) (TryCastException.TryCastException s t1)
 
-fromNonNegativeIntegral :: (Integral s, Num t) => s -> Maybe t
-fromNonNegativeIntegral x = if x < 0 then Nothing else Just $ fromIntegral x
+instance
+  ( Show s
+  , Typeable.Typeable s
+  , Typeable.Typeable t
+  ) => Cast.Cast (TryCastException.TryCastException s t) String where
+  cast = show
 
-maybeTryCast
-  :: (s -> Maybe t) -> s -> Either (TryCastException.TryCastException s t) t
-maybeTryCast f s = case f s of
-  Nothing -> Left $ TryCastException.TryCastException s
-  Just t -> Right t
+instance
+  ( Show s
+  , Typeable.Typeable s
+  , Typeable.Typeable t
+  ) => Cast.Cast (TryCastException.TryCastException s t) Text.Text where
+  cast = Utility.via @String
+
+instance
+  ( Show s
+  , Typeable.Typeable s
+  , Typeable.Typeable t
+  ) => Cast.Cast (TryCastException.TryCastException s t) LazyText.Text where
+  cast = Utility.via @String
+
+fromNonNegativeIntegral
+  :: (Integral s, Num t) => s -> Either Exception.ArithException t
+fromNonNegativeIntegral x =
+  if x < 0 then Left Exception.Underflow else Right $ fromIntegral x
 
 -- | The maximum integral value that can be unambiguously represented as a
 -- 'Float'. Equal to 16,777,215.
diff --git a/src/lib/Witch/TryCastException.hs b/src/lib/Witch/TryCastException.hs
--- a/src/lib/Witch/TryCastException.hs
+++ b/src/lib/Witch/TryCastException.hs
@@ -9,22 +9,24 @@
 -- | This exception is thrown when a @TryCast@ conversion fails. It has the
 -- original @source@ value that caused the failure and it knows the @target@
 -- type it was trying to convert into.
-newtype TryCastException source target
-  = TryCastException source
-  deriving Eq
+data TryCastException source target = TryCastException
+  source
+  (Maybe Exception.SomeException)
 
 instance
   ( Show source
   , Typeable.Typeable source
   , Typeable.Typeable target
   ) => Show (TryCastException source target) where
-  showsPrec d (TryCastException x) =
+  showsPrec d (TryCastException x e) =
     showParen (d > 10)
       $ showString "TryCastException {- "
       . shows
           (Typeable.typeRep (Proxy.Proxy :: Proxy.Proxy (source -> target)))
       . showString " -} "
       . showsPrec 11 x
+      . showChar ' '
+      . showsPrec 11 e
 
 instance
   ( Show source
diff --git a/src/lib/Witch/Utility.hs b/src/lib/Witch/Utility.hs
--- a/src/lib/Witch/Utility.hs
+++ b/src/lib/Witch/Utility.hs
@@ -125,6 +125,44 @@
   -> Either (TryCastException.TryCastException source target) target
 tryInto = TryCast.tryCast
 
+-- | This function can be used to implement 'TryCast.tryCast' with a function
+-- that returns 'Maybe'. For example:
+--
+-- > -- Avoid this:
+-- > tryCast s = case f s of
+-- >   Nothing -> Left $ TryCastException s Nothing
+-- >   Just t -> Right t
+-- >
+-- > -- Prefer this:
+-- > tryCast = maybeTryCast f
+maybeTryCast
+  :: (source -> Maybe target)
+  -> source
+  -> Either (TryCastException.TryCastException source target) target
+maybeTryCast f s = case f s of
+  Nothing -> Left $ TryCastException.TryCastException s Nothing
+  Just t -> Right t
+
+-- | This function can be used to implement 'TryCast.tryCast' with a function
+-- that returns 'Either'. For example:
+--
+-- > -- Avoid this:
+-- > tryCast s = case f s of
+-- >   Left e -> Left . TryCastException s . Just $ toException e
+-- >   Right t -> Right t
+-- >
+-- > -- Prefer this:
+-- > tryCast = eitherTryCast f
+eitherTryCast
+  :: Exception.Exception exception
+  => (source -> Either exception target)
+  -> source
+  -> Either (TryCastException.TryCastException source target) target
+eitherTryCast f s = case f s of
+  Left e ->
+    Left . TryCastException.TryCastException s . Just $ Exception.toException e
+  Right t -> Right t
+
 -- | This is similar to 'via' except that it works with 'TryCast.TryCast'
 -- instances instead. This function is especially convenient because juggling
 -- the types in the 'TryCastException.TryCastException' can be tedious.
@@ -143,9 +181,11 @@
   => source
   -> Either (TryCastException.TryCastException source target) target
 tryVia s = case TryCast.tryCast s of
-  Left _ -> Left $ TryCastException.TryCastException s
+  Left (TryCastException.TryCastException _ e) ->
+    Left $ TryCastException.TryCastException s e
   Right u -> case TryCast.tryCast (u :: through) of
-    Left _ -> Left $ TryCastException.TryCastException s
+    Left (TryCastException.TryCastException _ e) ->
+      Left $ TryCastException.TryCastException s e
     Right t -> Right t
 
 -- | This function is like 'TryCast.tryCast' except that it will throw an
diff --git a/src/test/Main.hs b/src/test/Main.hs
--- a/src/test/Main.hs
+++ b/src/test/Main.hs
@@ -9,1645 +9,1659 @@
 import qualified Data.ByteString.Lazy as LazyByteString
 import qualified Data.ByteString.Short as ShortByteString
 import qualified Data.Complex as Complex
-import qualified Data.Either as Either
-import qualified Data.Fixed as Fixed
-import qualified Data.Int as Int
-import qualified Data.IntMap as IntMap
-import qualified Data.IntSet as IntSet
-import qualified Data.List.NonEmpty as NonEmpty
-import qualified Data.Map as Map
-import qualified Data.Ratio as Ratio
-import qualified Data.Sequence as Seq
-import qualified Data.Set as Set
-import qualified Data.Text as Text
-import qualified Data.Text.Lazy as LazyText
-import qualified Data.Word as Word
-import qualified Numeric.Natural as Natural
-import qualified Test.Hspec as Hspec
-import qualified Witch
-
-main :: IO ()
-main = Hspec.hspec . Hspec.describe "Witch" $ do
-
-  Hspec.describe "Cast" $ do
-
-    Hspec.describe "cast" $ do
-      test $ Witch.cast (1 :: Int.Int8) `Hspec.shouldBe` (1 :: Int.Int16)
-
-  Hspec.describe "TryCast" $ do
-
-    Hspec.describe "tryCast" $ do
-      test $ Witch.tryCast (1 :: Int.Int16) `Hspec.shouldBe` Right (1 :: Int.Int8)
-      test $ Witch.tryCast 128 `Hspec.shouldBe` Left (Witch.TryCastException @Int.Int16 @Int.Int8 128)
-
-  Hspec.describe "Utility" $ do
-
-    Hspec.describe "as" $ do
-      test $ Witch.as @Int.Int8 1 `Hspec.shouldBe` 1
-
-    Hspec.describe "from" $ do
-      test $ Witch.from @Int.Int8 1 `Hspec.shouldBe` (1 :: Int.Int16)
-
-    Hspec.describe "into" $ do
-      test $ Witch.into @Int.Int16 (1 :: Int.Int8) `Hspec.shouldBe` 1
-
-    Hspec.describe "over" $ do
-      test $ Witch.over @String (<> "!") (Name "Kiki") `Hspec.shouldBe` Name "Kiki!"
-
-    Hspec.describe "via" $ do
-      test $ Witch.via @Int.Int16 (1 :: Int.Int8) `Hspec.shouldBe` (1 :: Int.Int32)
-
-    Hspec.describe "tryFrom" $ do
-      test $ Witch.tryFrom @Int.Int16 1 `Hspec.shouldBe` Right (1 :: Int.Int8)
-
-    Hspec.describe "tryInto" $ do
-      test $ Witch.tryInto @Int.Int8 (1 :: Int.Int16) `Hspec.shouldBe` Right 1
-
-    Hspec.describe "unsafeCast" $ do
-      test $ Witch.unsafeCast (1 :: Int.Int16) `Hspec.shouldBe` (1 :: Int.Int8)
-      test $ Exception.evaluate (Witch.unsafeCast @Int.Int16 @Int.Int8 128) `Hspec.shouldThrow` (== Witch.TryCastException @Int.Int16 @Int.Int8 128)
-
-    Hspec.describe "unsafeFrom" $ do
-      test $ Witch.unsafeFrom @Int.Int16 1 `Hspec.shouldBe` (1 :: Int.Int8)
-
-    Hspec.describe "unsafeInto" $ do
-      test $ Witch.unsafeInto @Int.Int8 (1 :: Int.Int16) `Hspec.shouldBe` 1
-
-  Hspec.describe "Lift" $ do
-
-    Hspec.describe "liftedCast" $ do
-      test $ ($$(Witch.liftedCast (1 :: Int.Int16)) :: Int.Int8) `Hspec.shouldBe` 1
-
-    Hspec.describe "liftedFrom" $ do
-      test $ ($$(Witch.liftedFrom @Int.Int16 1) :: Int.Int8) `Hspec.shouldBe` 1
-
-    Hspec.describe "liftedInto" $ do
-      test $ $$(Witch.liftedInto @Int.Int8 (1 :: Int.Int16)) `Hspec.shouldBe` 1
-
-  Hspec.describe "Instances" $ do
-
-    -- Int8
-
-    Hspec.describe "Cast Int8 Int16" $ do
-      let f = Witch.cast @Int.Int8 @Int.Int16
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 127 `Hspec.shouldBe` 127
-      test $ f (-128) `Hspec.shouldBe` (-128)
-
-    Hspec.describe "Cast Int8 Int32" $ do
-      let f = Witch.cast @Int.Int8 @Int.Int32
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 127 `Hspec.shouldBe` 127
-      test $ f (-128) `Hspec.shouldBe` (-128)
-
-    Hspec.describe "Cast Int8 Int64" $ do
-      let f = Witch.cast @Int.Int8 @Int.Int64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 127 `Hspec.shouldBe` 127
-      test $ f (-128) `Hspec.shouldBe` (-128)
-
-    Hspec.describe "Cast Int8 Int" $ do
-      let f = Witch.cast @Int.Int8 @Int
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 127 `Hspec.shouldBe` 127
-      test $ f (-128) `Hspec.shouldBe` (-128)
-
-    Hspec.describe "Cast Int8 Integer" $ do
-      let f = Witch.cast @Int.Int8 @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 127 `Hspec.shouldBe` 127
-      test $ f (-128) `Hspec.shouldBe` (-128)
-
-    Hspec.describe "TryCast Int8 Word8" $ do
-      let f = Witch.tryCast @Int.Int8 @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int8 Word16" $ do
-      let f = Witch.tryCast @Int.Int8 @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int8 Word32" $ do
-      let f = Witch.tryCast @Int.Int8 @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int8 Word64" $ do
-      let f = Witch.tryCast @Int.Int8 @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int8 Word" $ do
-      let f = Witch.tryCast @Int.Int8 @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int8 Natural" $ do
-      let f = Witch.tryCast @Int.Int8 @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Int8 Float" $ do
-      let f = Witch.cast @Int.Int8 @Float
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 127 `Hspec.shouldBe` 127
-      test $ f (-128) `Hspec.shouldBe` (-128)
-
-    Hspec.describe "Cast Int8 Double" $ do
-      let f = Witch.cast @Int.Int8 @Double
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 127 `Hspec.shouldBe` 127
-      test $ f (-128) `Hspec.shouldBe` (-128)
-
-    -- Int16
-
-    Hspec.describe "TryCast Int16 Int8" $ do
-      let f = Witch.tryCast @Int.Int16 @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-128) `Hspec.shouldBe` Right (-128)
-      test $ f (-129) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Int16 Int32" $ do
-      let f = Witch.cast @Int.Int16 @Int.Int32
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 32767 `Hspec.shouldBe` 32767
-      test $ f (-32768) `Hspec.shouldBe` (-32768)
-
-    Hspec.describe "Cast Int16 Int64" $ do
-      let f = Witch.cast @Int.Int16 @Int.Int64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 32767 `Hspec.shouldBe` 32767
-      test $ f (-32768) `Hspec.shouldBe` (-32768)
-
-    Hspec.describe "Cast Int16 Int" $ do
-      let f = Witch.cast @Int.Int16 @Int
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 32767 `Hspec.shouldBe` 32767
-      test $ f (-32768) `Hspec.shouldBe` (-32768)
-
-    Hspec.describe "Cast Int16 Integer" $ do
-      let f = Witch.cast @Int.Int16 @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 32767 `Hspec.shouldBe` 32767
-      test $ f (-32768) `Hspec.shouldBe` (-32768)
-
-    Hspec.describe "TryCast Int16 Word8" $ do
-      let f = Witch.tryCast @Int.Int16 @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int16 Word16" $ do
-      let f = Witch.tryCast @Int.Int16 @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int16 Word32" $ do
-      let f = Witch.tryCast @Int.Int16 @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int16 Word64" $ do
-      let f = Witch.tryCast @Int.Int16 @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int16 Word" $ do
-      let f = Witch.tryCast @Int.Int16 @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int16 Natural" $ do
-      let f = Witch.tryCast @Int.Int16 @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Int16 Float" $ do
-      let f = Witch.cast @Int.Int16 @Float
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 32767 `Hspec.shouldBe` 32767
-      test $ f (-32768) `Hspec.shouldBe` (-32768)
-
-    Hspec.describe "Cast Int16 Double" $ do
-      let f = Witch.cast @Int.Int16 @Double
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 32767 `Hspec.shouldBe` 32767
-      test $ f (-32768) `Hspec.shouldBe` (-32768)
-
-    -- Int32
-
-    Hspec.describe "TryCast Int32 Int8" $ do
-      let f = Witch.tryCast @Int.Int32 @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-128) `Hspec.shouldBe` Right (-128)
-      test $ f (-129) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int32 Int16" $ do
-      let f = Witch.tryCast @Int.Int32 @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-32768) `Hspec.shouldBe` Right (-32768)
-      test $ f (-32769) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Int32 Int64" $ do
-      let f = Witch.cast @Int.Int32 @Int.Int64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 2147483647 `Hspec.shouldBe` 2147483647
-      test $ f (-2147483648) `Hspec.shouldBe` (-2147483648)
-
-    Hspec.describe "TryCast Int32 Int" $ do
-      Monad.when (toInteger (maxBound :: Int) < 2147483647) untested
-      let f = Witch.tryCast @Int.Int32 @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f (-2147483648) `Hspec.shouldBe` Right (-2147483648)
-
-    Hspec.describe "Cast Int32 Integer" $ do
-      let f = Witch.cast @Int.Int32 @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 2147483647 `Hspec.shouldBe` 2147483647
-      test $ f (-2147483648) `Hspec.shouldBe` (-2147483648)
-
-    Hspec.describe "TryCast Int32 Word8" $ do
-      let f = Witch.tryCast @Int.Int32 @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int32 Word16" $ do
-      let f = Witch.tryCast @Int.Int32 @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int32 Word32" $ do
-      let f = Witch.tryCast @Int.Int32 @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int32 Word64" $ do
-      let f = Witch.tryCast @Int.Int32 @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int32 Word" $ do
-      Monad.when (toInteger (maxBound :: Word) < 2147483647) untested
-      let f = Witch.tryCast @Int.Int32 @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int32 Natural" $ do
-      let f = Witch.tryCast @Int.Int32 @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int32 Float" $ do
-      let f = Witch.tryCast @Int.Int32 @Float
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f (-16777216) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Int32 Double" $ do
-      let f = Witch.cast @Int.Int32 @Double
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 2147483647 `Hspec.shouldBe` 2147483647
-      test $ f (-2147483648) `Hspec.shouldBe` (-2147483648)
-
-    -- Int64
-
-    Hspec.describe "TryCast Int64 Int8" $ do
-      let f = Witch.tryCast @Int.Int64 @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-128) `Hspec.shouldBe` Right (-128)
-      test $ f (-129) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Int16" $ do
-      let f = Witch.tryCast @Int.Int64 @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-32768) `Hspec.shouldBe` Right (-32768)
-      test $ f (-32769) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Int32" $ do
-      let f = Witch.tryCast @Int.Int64 @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f 2147483648 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-2147483648) `Hspec.shouldBe` Right (-2147483648)
-      test $ f (-2147483649) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Int" $ do
-      Monad.when (toInteger (maxBound :: Int) < 9223372036854775807) untested
-      let f = Witch.tryCast @Int.Int64 @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` Right 9223372036854775807
-      test $ f (-9223372036854775808) `Hspec.shouldBe` Right (-9223372036854775808)
-
-    Hspec.describe "Cast Int64 Integer" $ do
-      let f = Witch.cast @Int.Int64 @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` 9223372036854775807
-      test $ f (-9223372036854775808) `Hspec.shouldBe` (-9223372036854775808)
-
-    Hspec.describe "TryCast Int64 Word8" $ do
-      let f = Witch.tryCast @Int.Int64 @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Word16" $ do
-      let f = Witch.tryCast @Int.Int64 @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Word32" $ do
-      let f = Witch.tryCast @Int.Int64 @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Word64" $ do
-      let f = Witch.tryCast @Int.Int64 @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` Right 9223372036854775807
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Word" $ do
-      Monad.when (toInteger (maxBound :: Word) < 9223372036854775807) untested
-      let f = Witch.tryCast @Int.Int64 @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` Right 9223372036854775807
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Natural" $ do
-      let f = Witch.tryCast @Int.Int64 @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` Right 9223372036854775807
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Float" $ do
-      let f = Witch.tryCast @Int.Int64 @Float
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f (-16777216) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int64 Double" $ do
-      let f = Witch.tryCast @Int.Int64 @Double
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-9007199254740991) `Hspec.shouldBe` Right (-9007199254740991)
-      test $ f (-9007199254740992) `Hspec.shouldSatisfy` Either.isLeft
-
-    -- Int
-
-    Hspec.describe "TryCast Int Int8" $ do
-      let f = Witch.tryCast @Int @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-128) `Hspec.shouldBe` Right (-128)
-      test $ f (-129) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Int16" $ do
-      let f = Witch.tryCast @Int @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-32768) `Hspec.shouldBe` Right (-32768)
-      test $ f (-32769) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Int32" $ do
-      Monad.when (toInteger (maxBound :: Int) < 2147483647) untested
-      let f = Witch.tryCast @Int @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f 2147483648 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-2147483648) `Hspec.shouldBe` Right (-2147483648)
-      test $ f (-2147483649) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Int Int64" $ do
-      let f = Witch.cast @Int @Int.Int64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Int)
-      test $ f minBound `Hspec.shouldBe` fromIntegral (minBound :: Int)
-
-    Hspec.describe "Cast Int Integer" $ do
-      let f = Witch.cast @Int @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Int)
-      test $ f minBound `Hspec.shouldBe` fromIntegral (minBound :: Int)
-
-    Hspec.describe "TryCast Int Word8" $ do
-      let f = Witch.tryCast @Int @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Word16" $ do
-      let f = Witch.tryCast @Int @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Word32" $ do
-      Monad.when (toInteger (maxBound :: Int) < 4294967295) untested
-      let f = Witch.tryCast @Int @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 4294967295 `Hspec.shouldBe` Right 4294967295
-      test $ f 4294967296 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Word64" $ do
-      let f = Witch.tryCast @Int @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f maxBound `Hspec.shouldBe` Right (fromIntegral (maxBound :: Int))
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Word" $ do
-      let f = Witch.tryCast @Int @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f maxBound `Hspec.shouldBe` Right (fromIntegral (maxBound :: Int))
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Natural" $ do
-      let f = Witch.tryCast @Int @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f maxBound `Hspec.shouldBe` Right (fromIntegral (maxBound :: Int))
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Float" $ do
-      let f = Witch.tryCast @Int @Float
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f (-16777216) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Int Double" $ do
-      Monad.when (toInteger (maxBound :: Int) < 9007199254740991) untested
-      let f = Witch.tryCast @Int @Double
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-9007199254740991) `Hspec.shouldBe` Right (-9007199254740991)
-      test $ f (-9007199254740992) `Hspec.shouldSatisfy` Either.isLeft
-
-    -- Integer
-
-    Hspec.describe "TryCast Integer Int8" $ do
-      let f = Witch.tryCast @Integer @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-128) `Hspec.shouldBe` Right (-128)
-      test $ f (-129) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Int16" $ do
-      let f = Witch.tryCast @Integer @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-32768) `Hspec.shouldBe` Right (-32768)
-      test $ f (-32769) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Int32" $ do
-      let f = Witch.tryCast @Integer @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f 2147483648 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-2147483648) `Hspec.shouldBe` Right (-2147483648)
-      test $ f (-2147483649) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Int64" $ do
-      let f = Witch.tryCast @Integer @Int.Int64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` Right 9223372036854775807
-      test $ f 9223372036854775808 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-9223372036854775808) `Hspec.shouldBe` Right (-9223372036854775808)
-      test $ f (-9223372036854775809) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Int" $ do
-      let f = Witch.tryCast @Integer @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ let x = maxBound :: Int in f (fromIntegral x) `Hspec.shouldBe` Right x
-      test $ let x = toInteger (maxBound :: Int) + 1 in f x `Hspec.shouldSatisfy` Either.isLeft
-      test $ let x = minBound :: Int in f (fromIntegral x) `Hspec.shouldBe` Right x
-      test $ let x = toInteger (minBound :: Int) - 1 in f x `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Word8" $ do
-      let f = Witch.tryCast @Integer @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Word16" $ do
-      let f = Witch.tryCast @Integer @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Word32" $ do
-      let f = Witch.tryCast @Integer @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 4294967295 `Hspec.shouldBe` Right 4294967295
-      test $ f 4294967296 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Word64" $ do
-      let f = Witch.tryCast @Integer @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 18446744073709551615 `Hspec.shouldBe` Right 18446744073709551615
-      test $ f 18446744073709551616 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Word" $ do
-      let f = Witch.tryCast @Integer @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ let x = maxBound :: Word in f (fromIntegral x) `Hspec.shouldBe` Right x
-      test $ let x = toInteger (maxBound :: Word) + 1 in f x `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Natural" $ do
-      let f = Witch.tryCast @Integer @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 18446744073709551616 `Hspec.shouldBe` Right 18446744073709551616
-      test $ f (-1) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Float" $ do
-      let f = Witch.tryCast @Integer @Float
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f (-16777216) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Integer Double" $ do
-      let f = Witch.tryCast @Integer @Double
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-9007199254740991) `Hspec.shouldBe` Right (-9007199254740991)
-      test $ f (-9007199254740992) `Hspec.shouldSatisfy` Either.isLeft
-
-    -- Word8
-
-    Hspec.describe "Cast Word8 Word16" $ do
-      let f = Witch.cast @Word.Word8 @Word.Word16
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Word32" $ do
-      let f = Witch.cast @Word.Word8 @Word.Word32
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Word64" $ do
-      let f = Witch.cast @Word.Word8 @Word.Word64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Word" $ do
-      let f = Witch.cast @Word.Word8 @Word
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Natural" $ do
-      let f = Witch.cast @Word.Word8 @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "TryCast Word8 Int8" $ do
-      let f = Witch.tryCast @Word.Word8 @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word8 Int16" $ do
-      let f = Witch.cast @Word.Word8 @Int.Int16
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Int32" $ do
-      let f = Witch.cast @Word.Word8 @Int.Int32
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Int64" $ do
-      let f = Witch.cast @Word.Word8 @Int.Int64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Int" $ do
-      let f = Witch.cast @Word.Word8 @Int
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Integer" $ do
-      let f = Witch.cast @Word.Word8 @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Float" $ do
-      let f = Witch.cast @Word.Word8 @Float
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    Hspec.describe "Cast Word8 Double" $ do
-      let f = Witch.cast @Word.Word8 @Double
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 255 `Hspec.shouldBe` 255
-
-    -- Word16
-
-    Hspec.describe "TryCast Word16 Word8" $ do
-      let f = Witch.tryCast @Word.Word16 @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word16 Word32" $ do
-      let f = Witch.cast @Word.Word16 @Word.Word32
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "Cast Word16 Word64" $ do
-      let f = Witch.cast @Word.Word16 @Word.Word64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "Cast Word16 Word" $ do
-      let f = Witch.cast @Word.Word16 @Word
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "Cast Word16 Natural" $ do
-      let f = Witch.cast @Word.Word16 @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "TryCast Word16 Int8" $ do
-      let f = Witch.tryCast @Word.Word16 @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word16 Int16" $ do
-      let f = Witch.tryCast @Word.Word16 @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word16 Int32" $ do
-      let f = Witch.cast @Word.Word16 @Int.Int32
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "Cast Word16 Int64" $ do
-      let f = Witch.cast @Word.Word16 @Int.Int64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "Cast Word16 Int" $ do
-      let f = Witch.cast @Word.Word16 @Int
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "Cast Word16 Integer" $ do
-      let f = Witch.cast @Word.Word16 @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "Cast Word16 Float" $ do
-      let f = Witch.cast @Word.Word16 @Float
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    Hspec.describe "Cast Word16 Double" $ do
-      let f = Witch.cast @Word.Word16 @Double
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 65535 `Hspec.shouldBe` 65535
-
-    -- Word32
-
-    Hspec.describe "TryCast Word32 Word8" $ do
-      let f = Witch.tryCast @Word.Word32 @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word32 Word16" $ do
-      let f = Witch.tryCast @Word.Word32 @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word32 Word64" $ do
-      let f = Witch.cast @Word.Word32 @Word.Word64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 4294967295 `Hspec.shouldBe` 4294967295
-
-    Hspec.describe "TryCast Word32 Word" $ do
-      Monad.when (toInteger (maxBound :: Word) < 4294967295) untested
-      let f = Witch.tryCast @Word.Word32 @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 4294967295 `Hspec.shouldBe` Right 4294967295
-
-    Hspec.describe "Cast Word32 Natural" $ do
-      let f = Witch.cast @Word.Word32 @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 4294967295 `Hspec.shouldBe` 4294967295
-
-    Hspec.describe "TryCast Word32 Int8" $ do
-      let f = Witch.tryCast @Word.Word32 @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word32 Int16" $ do
-      let f = Witch.tryCast @Word.Word32 @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word32 Int32" $ do
-      let f = Witch.tryCast @Word.Word32 @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f 2147483648 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word32 Int64" $ do
-      let f = Witch.cast @Word.Word32 @Int.Int64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 4294967295 `Hspec.shouldBe` 4294967295
-
-    Hspec.describe "TryCast Word32 Int" $ do
-      Monad.when (toInteger (maxBound :: Int) < 4294967295) untested
-      let f = Witch.tryCast @Word.Word32 @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 4294967295 `Hspec.shouldBe` Right 4294967295
-
-    Hspec.describe "Cast Word32 Integer" $ do
-      let f = Witch.cast @Word.Word32 @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 4294967295 `Hspec.shouldBe` 4294967295
-
-    Hspec.describe "TryCast Word32 Float" $ do
-      let f = Witch.tryCast @Word.Word32 @Float
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word32 Double" $ do
-      let f = Witch.cast @Word.Word32 @Double
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 4294967295 `Hspec.shouldBe` 4294967295
-
-    -- Word64
-
-    Hspec.describe "TryCast Word64 Word8" $ do
-      let f = Witch.tryCast @Word.Word64 @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word64 Word16" $ do
-      let f = Witch.tryCast @Word.Word64 @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word64 Word32" $ do
-      let f = Witch.tryCast @Word.Word64 @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 4294967295 `Hspec.shouldBe` Right 4294967295
-      test $ f 4294967296 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word64 Word" $ do
-      Monad.when (toInteger (maxBound :: Word) < 18446744073709551615) untested
-      let f = Witch.tryCast @Word.Word64 @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 18446744073709551615 `Hspec.shouldBe` Right 18446744073709551615
-
-    Hspec.describe "Cast Word64 Natural" $ do
-      let f = Witch.cast @Word.Word64 @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 18446744073709551615 `Hspec.shouldBe` 18446744073709551615
-
-    Hspec.describe "TryCast Word64 Int8" $ do
-      let f = Witch.tryCast @Word.Word64 @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word64 Int16" $ do
-      let f = Witch.tryCast @Word.Word64 @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word64 Int32" $ do
-      let f = Witch.tryCast @Word.Word64 @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f 2147483648 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word64 Int64" $ do
-      let f = Witch.tryCast @Word.Word64 @Int.Int64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` Right 9223372036854775807
-      test $ f 9223372036854775808 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word64 Int" $ do
-      let f = Witch.tryCast @Word.Word64 @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ let x = maxBound :: Int in Witch.tryCast @Word.Word64 @Int (fromIntegral x) `Hspec.shouldBe` Right x
-      test $ let x = fromIntegral (maxBound :: Int) + 1 :: Word.Word64 in Witch.tryCast @Word.Word64 @Int x `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word64 Integer" $ do
-      let f = Witch.cast @Word.Word64 @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 18446744073709551615 `Hspec.shouldBe` 18446744073709551615
-
-    Hspec.describe "TryCast Word64 Float" $ do
-      let f = Witch.tryCast @Word.Word64 @Float
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word64 Double" $ do
-      let f = Witch.tryCast @Word.Word64 @Double
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-
-    -- Word
-
-    Hspec.describe "TryCast Word Word8" $ do
-      let f = Witch.tryCast @Word @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word Word16" $ do
-      let f = Witch.tryCast @Word @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word Word32" $ do
-      Monad.when (toInteger (maxBound :: Word) < 4294967295) untested
-      let f = Witch.tryCast @Word @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 4294967295 `Hspec.shouldBe` Right 4294967295
-      test $ f 4294967296 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word Word64" $ do
-      let f = Witch.cast @Word @Word.Word64
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Word)
-
-    Hspec.describe "Cast Word Natural" $ do
-      let f = Witch.cast @Word @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Word)
-
-    Hspec.describe "TryCast Word Int8" $ do
-      let f = Witch.tryCast @Word @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word Int16" $ do
-      let f = Witch.tryCast @Word @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word Int32" $ do
-      Monad.when (toInteger (maxBound :: Word) < 2147483647) untested
-      let f = Witch.tryCast @Word @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f 2147483648 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word Int64" $ do
-      Monad.when (toInteger (maxBound :: Word) < 9223372036854775807) untested
-      let f = Witch.tryCast @Word @Int.Int64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` Right 9223372036854775807
-      test $ f 9223372036854775808 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word Int" $ do
-      let f = Witch.tryCast @Word @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ let x = maxBound :: Int in Witch.tryCast @Word @Int (fromIntegral x) `Hspec.shouldBe` Right x
-      test $ let x = fromIntegral (maxBound :: Int) + 1 :: Word in Witch.tryCast @Word @Int x `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Word Integer" $ do
-      let f = Witch.cast @Word @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Word)
-
-    Hspec.describe "TryCast Word Float" $ do
-      let f = Witch.tryCast @Word @Float
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Word Double" $ do
-      Monad.when (toInteger (maxBound :: Word) < 9007199254740991) untested
-      let f = Witch.tryCast @Word @Double
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-
-    -- Natural
-
-    Hspec.describe "TryCast Natural Word8" $ do
-      let f = Witch.tryCast @Natural.Natural @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Word16" $ do
-      let f = Witch.tryCast @Natural.Natural @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Word32" $ do
-      let f = Witch.tryCast @Natural.Natural @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 4294967295 `Hspec.shouldBe` Right 4294967295
-      test $ f 4294967296 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Word64" $ do
-      let f = Witch.tryCast @Natural.Natural @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 18446744073709551615 `Hspec.shouldBe` Right 18446744073709551615
-      test $ f 18446744073709551616 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Word" $ do
-      let f = Witch.tryCast @Natural.Natural @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ let x = maxBound :: Word in Witch.tryCast @Natural.Natural @Word (fromIntegral x) `Hspec.shouldBe` Right x
-      test $ let x = fromIntegral (maxBound :: Word) + 1 :: Natural.Natural in Witch.tryCast @Natural.Natural @Word x `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Int8" $ do
-      let f = Witch.tryCast @Natural.Natural @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Int16" $ do
-      let f = Witch.tryCast @Natural.Natural @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Int32" $ do
-      let f = Witch.tryCast @Natural.Natural @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f 2147483648 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Int64" $ do
-      let f = Witch.tryCast @Natural.Natural @Int.Int64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9223372036854775807 `Hspec.shouldBe` Right 9223372036854775807
-      test $ f 9223372036854775808 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Int" $ do
-      let f = Witch.tryCast @Natural.Natural @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ let x = maxBound :: Int in Witch.tryCast @Natural.Natural @Int (fromIntegral x) `Hspec.shouldBe` Right x
-      test $ let x = fromIntegral (maxBound :: Int) + 1 :: Natural.Natural in Witch.tryCast @Natural.Natural @Int x `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Natural Integer" $ do
-      let f = Witch.cast @Natural.Natural @Integer
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 9223372036854775808 `Hspec.shouldBe` 9223372036854775808
-
-    Hspec.describe "TryCast Natural Float" $ do
-      let f = Witch.tryCast @Natural.Natural @Float
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Natural Double" $ do
-      let f = Witch.tryCast @Natural.Natural @Double
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-
-    -- Float
-
-    Hspec.describe "TryCast Float Int8" $ do
-      let f = Witch.tryCast @Float @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-128) `Hspec.shouldBe` Right (-128)
-      test $ f (-129) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Int16" $ do
-      let f = Witch.tryCast @Float @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-32768) `Hspec.shouldBe` Right (-32768)
-      test $ f (-32769) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Int32" $ do
-      let f = Witch.tryCast @Float @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f (-16777216) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Int64" $ do
-      let f = Witch.tryCast @Float @Int.Int64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f (-16777216) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Int" $ do
-      let f = Witch.tryCast @Float @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f (-16777216) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Integer" $ do
-      let f = Witch.tryCast @Float @Integer
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f (-16777216) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Word8" $ do
-      let f = Witch.tryCast @Float @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Word16" $ do
-      let f = Witch.tryCast @Float @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Word32" $ do
-      let f = Witch.tryCast @Float @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Word64" $ do
-      let f = Witch.tryCast @Float @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Word" $ do
-      let f = Witch.tryCast @Float @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Natural" $ do
-      let f = Witch.tryCast @Float @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f 16777216 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Float Rational" $ do
-      let f = Witch.tryCast @Float @Rational
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f (-0) `Hspec.shouldBe` Right 0
-      test $ f 0.5 `Hspec.shouldBe` Right 0.5
-      test $ f (-0.5) `Hspec.shouldBe` Right (-0.5)
-      test $ f 16777215 `Hspec.shouldBe` Right 16777215
-      test $ f (-16777215) `Hspec.shouldBe` Right (-16777215)
-      test $ f 16777216 `Hspec.shouldBe` Right 16777216
-      test $ f (-16777216) `Hspec.shouldBe` Right (-16777216)
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Float Double" $ do
-      let f = Witch.cast @Float @Double
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 0.5 `Hspec.shouldBe` 0.5
-      test $ f (-0.5) `Hspec.shouldBe` (-0.5)
-      test $ f (0 / 0) `Hspec.shouldSatisfy` isNaN
-      test $ f (1 / 0) `Hspec.shouldBe` (1 / 0)
-      test $ f (-1 / 0) `Hspec.shouldBe` (-1 / 0)
-
-    -- Double
-
-    Hspec.describe "TryCast Double Int8" $ do
-      let f = Witch.tryCast @Double @Int.Int8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 127 `Hspec.shouldBe` Right 127
-      test $ f 128 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-128) `Hspec.shouldBe` Right (-128)
-      test $ f (-129) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Int16" $ do
-      let f = Witch.tryCast @Double @Int.Int16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 32767 `Hspec.shouldBe` Right 32767
-      test $ f 32768 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-32768) `Hspec.shouldBe` Right (-32768)
-      test $ f (-32769) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Int32" $ do
-      let f = Witch.tryCast @Double @Int.Int32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 2147483647 `Hspec.shouldBe` Right 2147483647
-      test $ f 2147483648 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-2147483648) `Hspec.shouldBe` Right (-2147483648)
-      test $ f (-2147483649) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Int64" $ do
-      let f = Witch.tryCast @Double @Int.Int64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-9007199254740991) `Hspec.shouldBe` Right (-9007199254740991)
-      test $ f (-9007199254740992) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Int" $ do
-      Monad.when (toInteger (maxBound :: Int) < 9007199254740991) untested
-      let f = Witch.tryCast @Double @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-9007199254740991) `Hspec.shouldBe` Right (-9007199254740991)
-      test $ f (-9007199254740992) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Integer" $ do
-      let f = Witch.tryCast @Double @Integer
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-9007199254740991) `Hspec.shouldBe` Right (-9007199254740991)
-      test $ f (-9007199254740992) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Word8" $ do
-      let f = Witch.tryCast @Double @Word.Word8
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 255 `Hspec.shouldBe` Right 255
-      test $ f 256 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Word16" $ do
-      let f = Witch.tryCast @Double @Word.Word16
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 65535 `Hspec.shouldBe` Right 65535
-      test $ f 65536 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Word32" $ do
-      let f = Witch.tryCast @Double @Word.Word32
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 4294967295 `Hspec.shouldBe` Right 4294967295
-      test $ f 4294967296 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Word64" $ do
-      let f = Witch.tryCast @Double @Word.Word64
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Word" $ do
-      Monad.when (toInteger (maxBound :: Word) < 9007199254740991) untested
-      let f = Witch.tryCast @Double @Word
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Natural" $ do
-      let f = Witch.tryCast @Double @Natural.Natural
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f 9007199254740992 `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "TryCast Double Rational" $ do
-      let f = Witch.tryCast @Double @Rational
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f (-0) `Hspec.shouldBe` Right 0
-      test $ f 0.5 `Hspec.shouldBe` Right 0.5
-      test $ f (-0.5) `Hspec.shouldBe` Right (-0.5)
-      test $ f 9007199254740991 `Hspec.shouldBe` Right 9007199254740991
-      test $ f (-9007199254740991) `Hspec.shouldBe` Right (-9007199254740991)
-      test $ f 9007199254740992 `Hspec.shouldBe` Right 9007199254740992
-      test $ f (-9007199254740992) `Hspec.shouldBe` Right (-9007199254740992)
-      test $ f (0 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-      test $ f (-1 / 0) `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Double Float" $ do
-      let f = Witch.cast @Double @Float
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 0.5 `Hspec.shouldBe` 0.5
-      test $ f (-0.5) `Hspec.shouldBe` (-0.5)
-      test $ f (0 / 0) `Hspec.shouldSatisfy` isNaN
-      test $ f (1 / 0) `Hspec.shouldBe` (1 / 0)
-      test $ f (-1 / 0) `Hspec.shouldBe` (-1 / 0)
-
-    -- Ratio
-
-    Hspec.describe "Cast a (Ratio a)" $ do
-      test $ Witch.cast @Integer @Rational 0 `Hspec.shouldBe` 0
-      let f = Witch.cast @Int @(Ratio.Ratio Int)
-      test $ f 0 `Hspec.shouldBe` 0
-
-    Hspec.describe "TryCast (Ratio a) a" $ do
-      test $ Witch.tryCast @Rational @Integer 0 `Hspec.shouldBe` Right 0
-      test $ Witch.tryCast @Rational @Integer 0.5 `Hspec.shouldSatisfy` Either.isLeft
-      let f = Witch.tryCast @(Ratio.Ratio Int) @Int
-      test $ f 0 `Hspec.shouldBe` Right 0
-      test $ f 0.5 `Hspec.shouldSatisfy` Either.isLeft
-
-    Hspec.describe "Cast Rational Float" $ do
-      let f = Witch.cast @Rational @Float
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 0.5 `Hspec.shouldBe` 0.5
-      test $ f (-0.5) `Hspec.shouldBe` (-0.5)
-
-    Hspec.describe "Cast Rational Double" $ do
-      let f = Witch.cast @Rational @Double
-      test $ f 0 `Hspec.shouldBe` 0
-      test $ f 0.5 `Hspec.shouldBe` 0.5
-      test $ f (-0.5) `Hspec.shouldBe` (-0.5)
-
-    -- Fixed
-
-    Hspec.describe "Cast Integer (Fixed a)" $ do
-      test $ Witch.cast @Integer @Fixed.Uni 1 `Hspec.shouldBe` 1
-      let f = Witch.cast @Integer @Fixed.Deci
-      test $ f 1 `Hspec.shouldBe` 0.1
-
-    Hspec.describe "Cast (Fixed a) Integer" $ do
-      test $ Witch.cast @Fixed.Uni @Integer 1 `Hspec.shouldBe` 1
-      let f = Witch.cast @Fixed.Deci @Integer
-      test $ f 1 `Hspec.shouldBe` 10
-
-    -- Complex
-
-    Hspec.describe "Cast a (Complex a)" $ do
-      test $ Witch.cast @Double @(Complex.Complex Double) 1 `Hspec.shouldBe` 1
-      let f = Witch.cast @Float @(Complex.Complex Float)
-      test $ f 1 `Hspec.shouldBe` 1
-
-    Hspec.describe "TryCast (Complex a) a" $ do
-      test $ Witch.tryCast @(Complex.Complex Double) @Double 1 `Hspec.shouldBe` Right 1
-      test $ Witch.tryCast @(Complex.Complex Double) @Double (0 Complex.:+ 1) `Hspec.shouldSatisfy` Either.isLeft
-      let f = Witch.tryCast @(Complex.Complex Float) @Float
-      test $ f 1 `Hspec.shouldBe` Right 1
-      test $ f (0 Complex.:+ 1) `Hspec.shouldSatisfy` Either.isLeft
-
-    -- NonEmpty
-
-    Hspec.describe "TryCast [a] (NonEmpty a)" $ do
-      let f = Witch.tryCast @[Int] @(NonEmpty.NonEmpty Int)
-      test $ f [] `Hspec.shouldSatisfy` Either.isLeft
-      test $ f [1] `Hspec.shouldBe` Right (1 NonEmpty.:| [])
-      test $ f [1, 2] `Hspec.shouldBe` Right (1 NonEmpty.:| [2])
-
-    Hspec.describe "Cast (NonEmpty a) [a]" $ do
-      let f = Witch.cast @(NonEmpty.NonEmpty Int) @[Int]
-      test $ f (1 NonEmpty.:| []) `Hspec.shouldBe` [1]
-      test $ f (1 NonEmpty.:| [2]) `Hspec.shouldBe` [1, 2]
-
-    -- Set
-
-    Hspec.describe "Cast [a] (Set a)" $ do
-      let f = Witch.cast @[Char] @(Set.Set Char)
-      test $ f [] `Hspec.shouldBe` Set.fromList []
-      test $ f ['a'] `Hspec.shouldBe` Set.fromList ['a']
-      test $ f ['a', 'b'] `Hspec.shouldBe` Set.fromList ['a', 'b']
-      test $ f ['a', 'a'] `Hspec.shouldBe` Set.fromList ['a']
-
-    Hspec.describe "Cast (Set a) [a]" $ do
-      let f = Witch.cast @(Set.Set Char) @[Char]
-      test $ f (Set.fromList []) `Hspec.shouldBe` []
-      test $ f (Set.fromList ['a']) `Hspec.shouldBe` ['a']
-      test $ f (Set.fromList ['a', 'b']) `Hspec.shouldBe` ['a', 'b']
-
-    -- IntSet
-
-    Hspec.describe "Cast [Int] IntSet" $ do
-      let f = Witch.cast @[Int] @IntSet.IntSet
-      test $ f [] `Hspec.shouldBe` IntSet.fromList []
-      test $ f [1] `Hspec.shouldBe` IntSet.fromList [1]
-      test $ f [1, 2] `Hspec.shouldBe` IntSet.fromList [1, 2]
-
-    Hspec.describe "Cast IntSet [Int]" $ do
-      let f = Witch.cast @IntSet.IntSet @[Int]
-      test $ f (IntSet.fromList []) `Hspec.shouldBe` []
-      test $ f (IntSet.fromList [1]) `Hspec.shouldBe` [1]
-      test $ f (IntSet.fromList [1, 2]) `Hspec.shouldBe` [1, 2]
-
-    -- Map
-
-    Hspec.describe "Cast [(k, v)] (Map k v)" $ do
-      let f = Witch.cast @[(Char, Int)] @(Map.Map Char Int)
-      test $ f [] `Hspec.shouldBe` Map.empty
-      test $ f [('a', 1)] `Hspec.shouldBe` Map.fromList [('a', 1)]
-      test $ f [('a', 1), ('b', 2)] `Hspec.shouldBe` Map.fromList [('a', 1), ('b', 2)]
-      test $ f [('a', 1), ('a', 2)] `Hspec.shouldBe` Map.fromList [('a', 2)]
-
-    Hspec.describe "Cast (Map k v) [(k, v)]" $ do
-      let f = Witch.cast @(Map.Map Char Int) @[(Char, Int)]
-      test $ f Map.empty `Hspec.shouldBe` []
-      test $ f (Map.fromList [('a', 1)]) `Hspec.shouldBe` [('a', 1)]
-      test $ f (Map.fromList [('a', 1), ('b', 2)]) `Hspec.shouldBe` [('a', 1), ('b', 2)]
-
-    -- IntMap
-
-    Hspec.describe "Cast [(Int, v)] (IntMap v)" $ do
-      let f = Witch.cast @[(Int, Char)] @(IntMap.IntMap Char)
-      test $ f [] `Hspec.shouldBe` IntMap.fromList []
-      test $ f [(1, 'a')] `Hspec.shouldBe` IntMap.fromList [(1, 'a')]
-      test $ f [(1, 'a'), (2, 'b')] `Hspec.shouldBe` IntMap.fromList [(1, 'a'), (2, 'b')]
-      test $ f [(1, 'a'), (1, 'b')] `Hspec.shouldBe` IntMap.fromList [(1, 'b')]
-
-    Hspec.describe "Cast (IntMap v) [(Int, v)]" $ do
-      let f = Witch.cast @(IntMap.IntMap Char) @[(Int, Char)]
-      test $ f (IntMap.fromList []) `Hspec.shouldBe` []
-      test $ f (IntMap.fromList [(1, 'a')]) `Hspec.shouldBe` [(1, 'a')]
-      test $ f (IntMap.fromList [(1, 'a'), (2, 'b')]) `Hspec.shouldBe` [(1, 'a'), (2, 'b')]
-
-    -- Seq
-
-    Hspec.describe "Cast [a] (Seq a)" $ do
-      let f = Witch.cast @[Int] @(Seq.Seq Int)
-      test $ f [] `Hspec.shouldBe` Seq.fromList []
-      test $ f [1] `Hspec.shouldBe` Seq.fromList [1]
-      test $ f [1, 2] `Hspec.shouldBe` Seq.fromList [1, 2]
-
-    Hspec.describe "Cast (Seq a) [a]" $ do
-      let f = Witch.cast @(Seq.Seq Int) @[Int]
-      test $ f (Seq.fromList []) `Hspec.shouldBe` []
-      test $ f (Seq.fromList [1]) `Hspec.shouldBe` [1]
-      test $ f (Seq.fromList [1, 2]) `Hspec.shouldBe` [1, 2]
-
-    -- ByteString
-
-    Hspec.describe "Cast [Word8] ByteString" $ do
-      let f = Witch.cast @[Word.Word8] @ByteString.ByteString
-      test $ f [] `Hspec.shouldBe` ByteString.pack []
-      test $ f [0x00] `Hspec.shouldBe` ByteString.pack [0x00]
-      test $ f [0x0f, 0xf0] `Hspec.shouldBe` ByteString.pack [0x0f, 0xf0]
-
-    Hspec.describe "Cast ByteString [Word8]" $ do
-      let f = Witch.cast @ByteString.ByteString @[Word.Word8]
-      test $ f (ByteString.pack []) `Hspec.shouldBe` []
-      test $ f (ByteString.pack [0x00]) `Hspec.shouldBe` [0x00]
-      test $ f (ByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` [0x0f, 0xf0]
-
-    Hspec.describe "Cast ByteString LazyByteString" $ do
-      let f = Witch.cast @ByteString.ByteString @LazyByteString.ByteString
-      test $ f (ByteString.pack []) `Hspec.shouldBe` LazyByteString.pack []
-      test $ f (ByteString.pack [0x00]) `Hspec.shouldBe` LazyByteString.pack [0x00]
-      test $ f (ByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` LazyByteString.pack [0x0f, 0xf0]
-
-    Hspec.describe "Cast ByteString ShortByteString" $ do
-      let f = Witch.cast @ByteString.ByteString @ShortByteString.ShortByteString
-      test $ f (ByteString.pack []) `Hspec.shouldBe` ShortByteString.pack []
-      test $ f (ByteString.pack [0x00]) `Hspec.shouldBe` ShortByteString.pack [0x00]
-      test $ f (ByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` ShortByteString.pack [0x0f, 0xf0]
-
-    Hspec.describe "TryCast ByteString Text" $ do
-      let f = Witch.tryCast @ByteString.ByteString @Text.Text
-      test $ f (ByteString.pack []) `Hspec.shouldBe` Right (Text.pack "")
-      test $ f (ByteString.pack [0x61]) `Hspec.shouldBe` Right (Text.pack "a")
-      test $ f (ByteString.pack [0xff]) `Hspec.shouldSatisfy` Either.isLeft
-
-    -- LazyByteString
-
-    Hspec.describe "Cast [Word8] LazyByteString" $ do
-      let f = Witch.cast @[Word.Word8] @LazyByteString.ByteString
-      test $ f [] `Hspec.shouldBe` LazyByteString.pack []
-      test $ f [0x00] `Hspec.shouldBe` LazyByteString.pack [0x00]
-      test $ f [0x0f, 0xf0] `Hspec.shouldBe` LazyByteString.pack [0x0f, 0xf0]
-
-    Hspec.describe "Cast LazyByteString [Word8]" $ do
-      let f = Witch.cast @LazyByteString.ByteString @[Word.Word8]
-      test $ f (LazyByteString.pack []) `Hspec.shouldBe` []
-      test $ f (LazyByteString.pack [0x00]) `Hspec.shouldBe` [0x00]
-      test $ f (LazyByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` [0x0f, 0xf0]
-
-    Hspec.describe "Cast LazyByteString ByteString" $ do
-      let f = Witch.cast @LazyByteString.ByteString @ByteString.ByteString
-      test $ f (LazyByteString.pack []) `Hspec.shouldBe` ByteString.pack []
-      test $ f (LazyByteString.pack [0x00]) `Hspec.shouldBe` ByteString.pack [0x00]
-      test $ f (LazyByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` ByteString.pack [0x0f, 0xf0]
-
-    Hspec.describe "TryCast LazyByteString LazyText" $ do
-      let f = Witch.tryCast @LazyByteString.ByteString @LazyText.Text
-      test $ f (LazyByteString.pack []) `Hspec.shouldBe` Right (LazyText.pack "")
-      test $ f (LazyByteString.pack [0x61]) `Hspec.shouldBe` Right (LazyText.pack "a")
-      test $ f (LazyByteString.pack [0xff]) `Hspec.shouldSatisfy` Either.isLeft
-
-    -- ShortByteString
-
-    Hspec.describe "Cast [Word8] ShortByteString" $ do
-      let f = Witch.cast @[Word.Word8] @ShortByteString.ShortByteString
-      test $ f [] `Hspec.shouldBe` ShortByteString.pack []
-      test $ f [0x00] `Hspec.shouldBe` ShortByteString.pack [0x00]
-      test $ f [0x0f, 0xf0] `Hspec.shouldBe` ShortByteString.pack [0x0f, 0xf0]
-
-    Hspec.describe "Cast ShortByteString [Word8]" $ do
-      let f = Witch.cast @ShortByteString.ShortByteString @[Word.Word8]
-      test $ f (ShortByteString.pack []) `Hspec.shouldBe` []
-      test $ f (ShortByteString.pack [0x00]) `Hspec.shouldBe` [0x00]
-      test $ f (ShortByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` [0x0f, 0xf0]
-
-    Hspec.describe "Cast ShortByteString ByteString" $ do
-      let f = Witch.cast @ShortByteString.ShortByteString @ByteString.ByteString
-      test $ f (ShortByteString.pack []) `Hspec.shouldBe` ByteString.pack []
-      test $ f (ShortByteString.pack [0x00]) `Hspec.shouldBe` ByteString.pack [0x00]
-      test $ f (ShortByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` ByteString.pack [0x0f, 0xf0]
-
-    -- Text
-
-    Hspec.describe "Cast String Text" $ do
-      let f = Witch.cast @String @Text.Text
-      test $ f "" `Hspec.shouldBe` Text.pack ""
-      test $ f "a" `Hspec.shouldBe` Text.pack "a"
-      test $ f "ab" `Hspec.shouldBe` Text.pack "ab"
-
-    Hspec.describe "Cast Text String" $ do
-      let f = Witch.cast @Text.Text @String
-      test $ f (Text.pack "") `Hspec.shouldBe` ""
-      test $ f (Text.pack "a") `Hspec.shouldBe` "a"
-      test $ f (Text.pack "ab") `Hspec.shouldBe` "ab"
-
-    Hspec.describe "Cast Text LazyText" $ do
-      let f = Witch.cast @Text.Text @LazyText.Text
-      test $ f (Text.pack "") `Hspec.shouldBe` LazyText.pack ""
-      test $ f (Text.pack "a") `Hspec.shouldBe` LazyText.pack "a"
-      test $ f (Text.pack "ab") `Hspec.shouldBe` LazyText.pack "ab"
-
-    Hspec.describe "Cast Text ByteString" $ do
-      let f = Witch.cast @Text.Text @ByteString.ByteString
-      test $ f (Text.pack "") `Hspec.shouldBe` ByteString.pack []
-      test $ f (Text.pack "a") `Hspec.shouldBe` ByteString.pack [0x61]
-
-    -- LazyText
-
-    Hspec.describe "Cast String LazyText" $ do
-      let f = Witch.cast @String @LazyText.Text
-      test $ f "" `Hspec.shouldBe` LazyText.pack ""
-      test $ f "a" `Hspec.shouldBe` LazyText.pack "a"
-      test $ f "ab" `Hspec.shouldBe` LazyText.pack "ab"
-
-    Hspec.describe "Cast LazyText String" $ do
-      let f = Witch.cast @LazyText.Text @String
-      test $ f (LazyText.pack "") `Hspec.shouldBe` ""
-      test $ f (LazyText.pack "a") `Hspec.shouldBe` "a"
-      test $ f (LazyText.pack "ab") `Hspec.shouldBe` "ab"
-
-    Hspec.describe "Cast LazyText Text" $ do
-      let f = Witch.cast @LazyText.Text @Text.Text
-      test $ f (LazyText.pack "") `Hspec.shouldBe` Text.pack ""
-      test $ f (LazyText.pack "a") `Hspec.shouldBe` Text.pack "a"
-      test $ f (LazyText.pack "ab") `Hspec.shouldBe` Text.pack "ab"
-
-    Hspec.describe "Cast LazyText LazyByteString" $ do
-      let f = Witch.cast @LazyText.Text @LazyByteString.ByteString
-      test $ f (LazyText.pack "") `Hspec.shouldBe` LazyByteString.pack []
-      test $ f (LazyText.pack "a") `Hspec.shouldBe` LazyByteString.pack [0x61]
-
-    -- TryCastException
-
-    Hspec.describe "Cast (TryCastException s t0) (TryCastException s t1)" $ do
-      let f = Witch.cast @(Witch.TryCastException () Int) @(Witch.TryCastException () Word)
-      test $ f (Witch.TryCastException ()) `Hspec.shouldBe` Witch.TryCastException ()
-
-test :: Hspec.Example a => a -> Hspec.SpecWith (Hspec.Arg a)
-test = Hspec.it ""
-
-untested :: Hspec.SpecWith a
-untested = Hspec.runIO $ Exception.throwIO Untested
+import qualified Data.Fixed as Fixed
+import qualified Data.Int as Int
+import qualified Data.IntMap as IntMap
+import qualified Data.IntSet as IntSet
+import qualified Data.List.NonEmpty as NonEmpty
+import qualified Data.Map as Map
+import qualified Data.Ratio as Ratio
+import qualified Data.Sequence as Seq
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import qualified Data.Text.Lazy as LazyText
+import qualified Data.Word as Word
+import qualified Numeric.Natural as Natural
+import qualified Test.Hspec as Hspec
+import qualified Witch
+
+main :: IO ()
+main = Hspec.hspec . Hspec.describe "Witch" $ do
+
+  Hspec.describe "Cast" $ do
+
+    Hspec.describe "cast" $ do
+      test $ Witch.cast (1 :: Int.Int8) `Hspec.shouldBe` (1 :: Int.Int16)
+
+  Hspec.describe "TryCast" $ do
+
+    Hspec.describe "tryCast" $ do
+      let f = hush . Witch.tryCast @Int.Int16 @Int.Int8
+      test $ f 1 `Hspec.shouldBe` Just 1
+      test $ f 128 `Hspec.shouldBe` Nothing
+
+  Hspec.describe "Utility" $ do
+
+    Hspec.describe "as" $ do
+      test $ Witch.as @Int.Int8 1 `Hspec.shouldBe` 1
+
+    Hspec.describe "from" $ do
+      test $ Witch.from @Int.Int8 1 `Hspec.shouldBe` (1 :: Int.Int16)
+
+    Hspec.describe "into" $ do
+      test $ Witch.into @Int.Int16 (1 :: Int.Int8) `Hspec.shouldBe` 1
+
+    Hspec.describe "over" $ do
+      test $ Witch.over @String (<> "!") (Name "Kiki") `Hspec.shouldBe` Name "Kiki!"
+
+    Hspec.describe "via" $ do
+      test $ Witch.via @Int.Int16 (1 :: Int.Int8) `Hspec.shouldBe` (1 :: Int.Int32)
+
+    Hspec.describe "tryFrom" $ do
+      test $ hush (Witch.tryFrom @Int.Int16 1) `Hspec.shouldBe` Just (1 :: Int.Int8)
+
+    Hspec.describe "tryInto" $ do
+      test $ hush (Witch.tryInto @Int.Int8 (1 :: Int.Int16)) `Hspec.shouldBe` Just 1
+
+    Hspec.describe "unsafeCast" $ do
+      test $ Witch.unsafeCast (1 :: Int.Int16) `Hspec.shouldBe` (1 :: Int.Int8)
+      test $ Exception.evaluate (Witch.unsafeCast @Int.Int16 @Int.Int8 128) `Hspec.shouldThrow` Hspec.anyException
+
+    Hspec.describe "unsafeFrom" $ do
+      test $ Witch.unsafeFrom @Int.Int16 1 `Hspec.shouldBe` (1 :: Int.Int8)
+
+    Hspec.describe "unsafeInto" $ do
+      test $ Witch.unsafeInto @Int.Int8 (1 :: Int.Int16) `Hspec.shouldBe` 1
+
+  Hspec.describe "Lift" $ do
+
+    Hspec.describe "liftedCast" $ do
+      test $ ($$(Witch.liftedCast (1 :: Int.Int16)) :: Int.Int8) `Hspec.shouldBe` 1
+
+    Hspec.describe "liftedFrom" $ do
+      test $ ($$(Witch.liftedFrom @Int.Int16 1) :: Int.Int8) `Hspec.shouldBe` 1
+
+    Hspec.describe "liftedInto" $ do
+      test $ $$(Witch.liftedInto @Int.Int8 (1 :: Int.Int16)) `Hspec.shouldBe` 1
+
+  Hspec.describe "Instances" $ do
+
+    -- Int8
+
+    Hspec.describe "Cast Int8 Int16" $ do
+      let f = Witch.cast @Int.Int8 @Int.Int16
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 127 `Hspec.shouldBe` 127
+      test $ f (-128) `Hspec.shouldBe` (-128)
+
+    Hspec.describe "Cast Int8 Int32" $ do
+      let f = Witch.cast @Int.Int8 @Int.Int32
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 127 `Hspec.shouldBe` 127
+      test $ f (-128) `Hspec.shouldBe` (-128)
+
+    Hspec.describe "Cast Int8 Int64" $ do
+      let f = Witch.cast @Int.Int8 @Int.Int64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 127 `Hspec.shouldBe` 127
+      test $ f (-128) `Hspec.shouldBe` (-128)
+
+    Hspec.describe "Cast Int8 Int" $ do
+      let f = Witch.cast @Int.Int8 @Int
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 127 `Hspec.shouldBe` 127
+      test $ f (-128) `Hspec.shouldBe` (-128)
+
+    Hspec.describe "Cast Int8 Integer" $ do
+      let f = Witch.cast @Int.Int8 @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 127 `Hspec.shouldBe` 127
+      test $ f (-128) `Hspec.shouldBe` (-128)
+
+    Hspec.describe "TryCast Int8 Word8" $ do
+      let f = hush . Witch.tryCast @Int.Int8 @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int8 Word16" $ do
+      let f = hush . Witch.tryCast @Int.Int8 @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int8 Word32" $ do
+      let f = hush . Witch.tryCast @Int.Int8 @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int8 Word64" $ do
+      let f = hush . Witch.tryCast @Int.Int8 @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int8 Word" $ do
+      let f = hush . Witch.tryCast @Int.Int8 @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int8 Natural" $ do
+      let f = hush . Witch.tryCast @Int.Int8 @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Int8 Float" $ do
+      let f = Witch.cast @Int.Int8 @Float
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 127 `Hspec.shouldBe` 127
+      test $ f (-128) `Hspec.shouldBe` (-128)
+
+    Hspec.describe "Cast Int8 Double" $ do
+      let f = Witch.cast @Int.Int8 @Double
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 127 `Hspec.shouldBe` 127
+      test $ f (-128) `Hspec.shouldBe` (-128)
+
+    -- Int16
+
+    Hspec.describe "TryCast Int16 Int8" $ do
+      let f = hush . Witch.tryCast @Int.Int16 @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+      test $ f (-128) `Hspec.shouldBe` Just (-128)
+      test $ f (-129) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Int16 Int32" $ do
+      let f = Witch.cast @Int.Int16 @Int.Int32
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 32767 `Hspec.shouldBe` 32767
+      test $ f (-32768) `Hspec.shouldBe` (-32768)
+
+    Hspec.describe "Cast Int16 Int64" $ do
+      let f = Witch.cast @Int.Int16 @Int.Int64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 32767 `Hspec.shouldBe` 32767
+      test $ f (-32768) `Hspec.shouldBe` (-32768)
+
+    Hspec.describe "Cast Int16 Int" $ do
+      let f = Witch.cast @Int.Int16 @Int
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 32767 `Hspec.shouldBe` 32767
+      test $ f (-32768) `Hspec.shouldBe` (-32768)
+
+    Hspec.describe "Cast Int16 Integer" $ do
+      let f = Witch.cast @Int.Int16 @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 32767 `Hspec.shouldBe` 32767
+      test $ f (-32768) `Hspec.shouldBe` (-32768)
+
+    Hspec.describe "TryCast Int16 Word8" $ do
+      let f = hush . Witch.tryCast @Int.Int16 @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int16 Word16" $ do
+      let f = hush . Witch.tryCast @Int.Int16 @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int16 Word32" $ do
+      let f = hush . Witch.tryCast @Int.Int16 @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int16 Word64" $ do
+      let f = hush . Witch.tryCast @Int.Int16 @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int16 Word" $ do
+      let f = hush . Witch.tryCast @Int.Int16 @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int16 Natural" $ do
+      let f = hush . Witch.tryCast @Int.Int16 @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Int16 Float" $ do
+      let f = Witch.cast @Int.Int16 @Float
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 32767 `Hspec.shouldBe` 32767
+      test $ f (-32768) `Hspec.shouldBe` (-32768)
+
+    Hspec.describe "Cast Int16 Double" $ do
+      let f = Witch.cast @Int.Int16 @Double
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 32767 `Hspec.shouldBe` 32767
+      test $ f (-32768) `Hspec.shouldBe` (-32768)
+
+    -- Int32
+
+    Hspec.describe "TryCast Int32 Int8" $ do
+      let f = hush . Witch.tryCast @Int.Int32 @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+      test $ f (-128) `Hspec.shouldBe` Just (-128)
+      test $ f (-129) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int32 Int16" $ do
+      let f = hush . Witch.tryCast @Int.Int32 @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+      test $ f (-32768) `Hspec.shouldBe` Just (-32768)
+      test $ f (-32769) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Int32 Int64" $ do
+      let f = Witch.cast @Int.Int32 @Int.Int64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 2147483647 `Hspec.shouldBe` 2147483647
+      test $ f (-2147483648) `Hspec.shouldBe` (-2147483648)
+
+    Hspec.describe "TryCast Int32 Int" $ do
+      Monad.when (toInteger (maxBound :: Int) < 2147483647) untested
+      let f = hush . Witch.tryCast @Int.Int32 @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f (-2147483648) `Hspec.shouldBe` Just (-2147483648)
+
+    Hspec.describe "Cast Int32 Integer" $ do
+      let f = Witch.cast @Int.Int32 @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 2147483647 `Hspec.shouldBe` 2147483647
+      test $ f (-2147483648) `Hspec.shouldBe` (-2147483648)
+
+    Hspec.describe "TryCast Int32 Word8" $ do
+      let f = hush . Witch.tryCast @Int.Int32 @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int32 Word16" $ do
+      let f = hush . Witch.tryCast @Int.Int32 @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int32 Word32" $ do
+      let f = hush . Witch.tryCast @Int.Int32 @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int32 Word64" $ do
+      let f = hush . Witch.tryCast @Int.Int32 @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int32 Word" $ do
+      Monad.when (toInteger (maxBound :: Word) < 2147483647) untested
+      let f = hush . Witch.tryCast @Int.Int32 @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int32 Natural" $ do
+      let f = hush . Witch.tryCast @Int.Int32 @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int32 Float" $ do
+      let f = hush . Witch.tryCast @Int.Int32 @Float
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f (-16777216) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Int32 Double" $ do
+      let f = Witch.cast @Int.Int32 @Double
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 2147483647 `Hspec.shouldBe` 2147483647
+      test $ f (-2147483648) `Hspec.shouldBe` (-2147483648)
+
+    -- Int64
+
+    Hspec.describe "TryCast Int64 Int8" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+      test $ f (-128) `Hspec.shouldBe` Just (-128)
+      test $ f (-129) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Int16" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+      test $ f (-32768) `Hspec.shouldBe` Just (-32768)
+      test $ f (-32769) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Int32" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f 2147483648 `Hspec.shouldBe` Nothing
+      test $ f (-2147483648) `Hspec.shouldBe` Just (-2147483648)
+      test $ f (-2147483649) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Int" $ do
+      Monad.when (toInteger (maxBound :: Int) < 9223372036854775807) untested
+      let f = hush . Witch.tryCast @Int.Int64 @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` Just 9223372036854775807
+      test $ f (-9223372036854775808) `Hspec.shouldBe` Just (-9223372036854775808)
+
+    Hspec.describe "Cast Int64 Integer" $ do
+      let f = Witch.cast @Int.Int64 @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` 9223372036854775807
+      test $ f (-9223372036854775808) `Hspec.shouldBe` (-9223372036854775808)
+
+    Hspec.describe "TryCast Int64 Word8" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Word16" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Word32" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Word64" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` Just 9223372036854775807
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Word" $ do
+      Monad.when (toInteger (maxBound :: Word) < 9223372036854775807) untested
+      let f = hush . Witch.tryCast @Int.Int64 @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` Just 9223372036854775807
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Natural" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` Just 9223372036854775807
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Float" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Float
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f (-16777216) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int64 Double" $ do
+      let f = hush . Witch.tryCast @Int.Int64 @Double
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (-9007199254740991) `Hspec.shouldBe` Just (-9007199254740991)
+      test $ f (-9007199254740992) `Hspec.shouldBe` Nothing
+
+    -- Int
+
+    Hspec.describe "TryCast Int Int8" $ do
+      let f = hush . Witch.tryCast @Int @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+      test $ f (-128) `Hspec.shouldBe` Just (-128)
+      test $ f (-129) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Int16" $ do
+      let f = hush . Witch.tryCast @Int @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+      test $ f (-32768) `Hspec.shouldBe` Just (-32768)
+      test $ f (-32769) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Int32" $ do
+      Monad.when (toInteger (maxBound :: Int) < 2147483647) untested
+      let f = hush . Witch.tryCast @Int @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f 2147483648 `Hspec.shouldBe` Nothing
+      test $ f (-2147483648) `Hspec.shouldBe` Just (-2147483648)
+      test $ f (-2147483649) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Int Int64" $ do
+      let f = Witch.cast @Int @Int.Int64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Int)
+      test $ f minBound `Hspec.shouldBe` fromIntegral (minBound :: Int)
+
+    Hspec.describe "Cast Int Integer" $ do
+      let f = Witch.cast @Int @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Int)
+      test $ f minBound `Hspec.shouldBe` fromIntegral (minBound :: Int)
+
+    Hspec.describe "TryCast Int Word8" $ do
+      let f = hush . Witch.tryCast @Int @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Word16" $ do
+      let f = hush . Witch.tryCast @Int @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Word32" $ do
+      Monad.when (toInteger (maxBound :: Int) < 4294967295) untested
+      let f = hush . Witch.tryCast @Int @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 4294967295 `Hspec.shouldBe` Just 4294967295
+      test $ f 4294967296 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Word64" $ do
+      let f = hush . Witch.tryCast @Int @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f maxBound `Hspec.shouldBe` Just (fromIntegral (maxBound :: Int))
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Word" $ do
+      let f = hush . Witch.tryCast @Int @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f maxBound `Hspec.shouldBe` Just (fromIntegral (maxBound :: Int))
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Natural" $ do
+      let f = hush . Witch.tryCast @Int @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f maxBound `Hspec.shouldBe` Just (fromIntegral (maxBound :: Int))
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Float" $ do
+      let f = hush . Witch.tryCast @Int @Float
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f (-16777216) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Int Double" $ do
+      Monad.when (toInteger (maxBound :: Int) < 9007199254740991) untested
+      let f = hush . Witch.tryCast @Int @Double
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (-9007199254740991) `Hspec.shouldBe` Just (-9007199254740991)
+      test $ f (-9007199254740992) `Hspec.shouldBe` Nothing
+
+    -- Integer
+
+    Hspec.describe "TryCast Integer Int8" $ do
+      let f = hush . Witch.tryCast @Integer @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+      test $ f (-128) `Hspec.shouldBe` Just (-128)
+      test $ f (-129) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Int16" $ do
+      let f = hush . Witch.tryCast @Integer @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+      test $ f (-32768) `Hspec.shouldBe` Just (-32768)
+      test $ f (-32769) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Int32" $ do
+      let f = hush . Witch.tryCast @Integer @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f 2147483648 `Hspec.shouldBe` Nothing
+      test $ f (-2147483648) `Hspec.shouldBe` Just (-2147483648)
+      test $ f (-2147483649) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Int64" $ do
+      let f = hush . Witch.tryCast @Integer @Int.Int64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` Just 9223372036854775807
+      test $ f 9223372036854775808 `Hspec.shouldBe` Nothing
+      test $ f (-9223372036854775808) `Hspec.shouldBe` Just (-9223372036854775808)
+      test $ f (-9223372036854775809) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Int" $ do
+      let f = hush . Witch.tryCast @Integer @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ let x = maxBound :: Int in f (fromIntegral x) `Hspec.shouldBe` Just x
+      test $ let x = toInteger (maxBound :: Int) + 1 in f x `Hspec.shouldBe` Nothing
+      test $ let x = minBound :: Int in f (fromIntegral x) `Hspec.shouldBe` Just x
+      test $ let x = toInteger (minBound :: Int) - 1 in f x `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Word8" $ do
+      let f = hush . Witch.tryCast @Integer @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Word16" $ do
+      let f = hush . Witch.tryCast @Integer @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Word32" $ do
+      let f = hush . Witch.tryCast @Integer @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 4294967295 `Hspec.shouldBe` Just 4294967295
+      test $ f 4294967296 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Word64" $ do
+      let f = hush . Witch.tryCast @Integer @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 18446744073709551615 `Hspec.shouldBe` Just 18446744073709551615
+      test $ f 18446744073709551616 `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Word" $ do
+      let f = hush . Witch.tryCast @Integer @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ let x = maxBound :: Word in f (fromIntegral x) `Hspec.shouldBe` Just x
+      test $ let x = toInteger (maxBound :: Word) + 1 in f x `Hspec.shouldBe` Nothing
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Natural" $ do
+      let f = hush . Witch.tryCast @Integer @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 18446744073709551616 `Hspec.shouldBe` Just 18446744073709551616
+      test $ f (-1) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Float" $ do
+      let f = hush . Witch.tryCast @Integer @Float
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f (-16777216) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Integer Double" $ do
+      let f = hush . Witch.tryCast @Integer @Double
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (-9007199254740991) `Hspec.shouldBe` Just (-9007199254740991)
+      test $ f (-9007199254740992) `Hspec.shouldBe` Nothing
+
+    -- Word8
+
+    Hspec.describe "Cast Word8 Word16" $ do
+      let f = Witch.cast @Word.Word8 @Word.Word16
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Word32" $ do
+      let f = Witch.cast @Word.Word8 @Word.Word32
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Word64" $ do
+      let f = Witch.cast @Word.Word8 @Word.Word64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Word" $ do
+      let f = Witch.cast @Word.Word8 @Word
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Natural" $ do
+      let f = Witch.cast @Word.Word8 @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "TryCast Word8 Int8" $ do
+      let f = hush . Witch.tryCast @Word.Word8 @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word8 Int16" $ do
+      let f = Witch.cast @Word.Word8 @Int.Int16
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Int32" $ do
+      let f = Witch.cast @Word.Word8 @Int.Int32
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Int64" $ do
+      let f = Witch.cast @Word.Word8 @Int.Int64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Int" $ do
+      let f = Witch.cast @Word.Word8 @Int
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Integer" $ do
+      let f = Witch.cast @Word.Word8 @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Float" $ do
+      let f = Witch.cast @Word.Word8 @Float
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    Hspec.describe "Cast Word8 Double" $ do
+      let f = Witch.cast @Word.Word8 @Double
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 255 `Hspec.shouldBe` 255
+
+    -- Word16
+
+    Hspec.describe "TryCast Word16 Word8" $ do
+      let f = hush . Witch.tryCast @Word.Word16 @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word16 Word32" $ do
+      let f = Witch.cast @Word.Word16 @Word.Word32
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "Cast Word16 Word64" $ do
+      let f = Witch.cast @Word.Word16 @Word.Word64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "Cast Word16 Word" $ do
+      let f = Witch.cast @Word.Word16 @Word
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "Cast Word16 Natural" $ do
+      let f = Witch.cast @Word.Word16 @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "TryCast Word16 Int8" $ do
+      let f = hush . Witch.tryCast @Word.Word16 @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word16 Int16" $ do
+      let f = hush . Witch.tryCast @Word.Word16 @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word16 Int32" $ do
+      let f = Witch.cast @Word.Word16 @Int.Int32
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "Cast Word16 Int64" $ do
+      let f = Witch.cast @Word.Word16 @Int.Int64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "Cast Word16 Int" $ do
+      let f = Witch.cast @Word.Word16 @Int
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "Cast Word16 Integer" $ do
+      let f = Witch.cast @Word.Word16 @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "Cast Word16 Float" $ do
+      let f = Witch.cast @Word.Word16 @Float
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    Hspec.describe "Cast Word16 Double" $ do
+      let f = Witch.cast @Word.Word16 @Double
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 65535 `Hspec.shouldBe` 65535
+
+    -- Word32
+
+    Hspec.describe "TryCast Word32 Word8" $ do
+      let f = hush . Witch.tryCast @Word.Word32 @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word32 Word16" $ do
+      let f = hush . Witch.tryCast @Word.Word32 @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word32 Word64" $ do
+      let f = Witch.cast @Word.Word32 @Word.Word64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 4294967295 `Hspec.shouldBe` 4294967295
+
+    Hspec.describe "TryCast Word32 Word" $ do
+      Monad.when (toInteger (maxBound :: Word) < 4294967295) untested
+      let f = hush . Witch.tryCast @Word.Word32 @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 4294967295 `Hspec.shouldBe` Just 4294967295
+
+    Hspec.describe "Cast Word32 Natural" $ do
+      let f = Witch.cast @Word.Word32 @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 4294967295 `Hspec.shouldBe` 4294967295
+
+    Hspec.describe "TryCast Word32 Int8" $ do
+      let f = hush . Witch.tryCast @Word.Word32 @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word32 Int16" $ do
+      let f = hush . Witch.tryCast @Word.Word32 @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word32 Int32" $ do
+      let f = hush . Witch.tryCast @Word.Word32 @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f 2147483648 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word32 Int64" $ do
+      let f = Witch.cast @Word.Word32 @Int.Int64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 4294967295 `Hspec.shouldBe` 4294967295
+
+    Hspec.describe "TryCast Word32 Int" $ do
+      Monad.when (toInteger (maxBound :: Int) < 4294967295) untested
+      let f = hush . Witch.tryCast @Word.Word32 @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 4294967295 `Hspec.shouldBe` Just 4294967295
+
+    Hspec.describe "Cast Word32 Integer" $ do
+      let f = Witch.cast @Word.Word32 @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 4294967295 `Hspec.shouldBe` 4294967295
+
+    Hspec.describe "TryCast Word32 Float" $ do
+      let f = hush . Witch.tryCast @Word.Word32 @Float
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word32 Double" $ do
+      let f = Witch.cast @Word.Word32 @Double
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 4294967295 `Hspec.shouldBe` 4294967295
+
+    -- Word64
+
+    Hspec.describe "TryCast Word64 Word8" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word64 Word16" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word64 Word32" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 4294967295 `Hspec.shouldBe` Just 4294967295
+      test $ f 4294967296 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word64 Word" $ do
+      Monad.when (toInteger (maxBound :: Word) < 18446744073709551615) untested
+      let f = hush . Witch.tryCast @Word.Word64 @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 18446744073709551615 `Hspec.shouldBe` Just 18446744073709551615
+
+    Hspec.describe "Cast Word64 Natural" $ do
+      let f = Witch.cast @Word.Word64 @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 18446744073709551615 `Hspec.shouldBe` 18446744073709551615
+
+    Hspec.describe "TryCast Word64 Int8" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word64 Int16" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word64 Int32" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f 2147483648 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word64 Int64" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Int.Int64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` Just 9223372036854775807
+      test $ f 9223372036854775808 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word64 Int" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ let x = maxBound :: Int in hush (Witch.tryCast @Word.Word64 @Int (fromIntegral x)) `Hspec.shouldBe` Just x
+      test $ let x = fromIntegral (maxBound :: Int) + 1 :: Word.Word64 in hush (Witch.tryCast @Word.Word64 @Int x) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word64 Integer" $ do
+      let f = Witch.cast @Word.Word64 @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 18446744073709551615 `Hspec.shouldBe` 18446744073709551615
+
+    Hspec.describe "TryCast Word64 Float" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Float
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word64 Double" $ do
+      let f = hush . Witch.tryCast @Word.Word64 @Double
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+
+    -- Word
+
+    Hspec.describe "TryCast Word Word8" $ do
+      let f = hush . Witch.tryCast @Word @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word Word16" $ do
+      let f = hush . Witch.tryCast @Word @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word Word32" $ do
+      Monad.when (toInteger (maxBound :: Word) < 4294967295) untested
+      let f = hush . Witch.tryCast @Word @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 4294967295 `Hspec.shouldBe` Just 4294967295
+      test $ f 4294967296 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word Word64" $ do
+      let f = Witch.cast @Word @Word.Word64
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Word)
+
+    Hspec.describe "Cast Word Natural" $ do
+      let f = Witch.cast @Word @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Word)
+
+    Hspec.describe "TryCast Word Int8" $ do
+      let f = hush . Witch.tryCast @Word @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word Int16" $ do
+      let f = hush . Witch.tryCast @Word @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word Int32" $ do
+      Monad.when (toInteger (maxBound :: Word) < 2147483647) untested
+      let f = hush . Witch.tryCast @Word @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f 2147483648 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word Int64" $ do
+      Monad.when (toInteger (maxBound :: Word) < 9223372036854775807) untested
+      let f = hush . Witch.tryCast @Word @Int.Int64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` Just 9223372036854775807
+      test $ f 9223372036854775808 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word Int" $ do
+      let f = hush . Witch.tryCast @Word @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ let x = maxBound :: Int in hush (Witch.tryCast @Word @Int (fromIntegral x)) `Hspec.shouldBe` Just x
+      test $ let x = fromIntegral (maxBound :: Int) + 1 :: Word in hush (Witch.tryCast @Word @Int x) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Word Integer" $ do
+      let f = Witch.cast @Word @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f maxBound `Hspec.shouldBe` fromIntegral (maxBound :: Word)
+
+    Hspec.describe "TryCast Word Float" $ do
+      let f = hush . Witch.tryCast @Word @Float
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Word Double" $ do
+      Monad.when (toInteger (maxBound :: Word) < 9007199254740991) untested
+      let f = hush . Witch.tryCast @Word @Double
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+
+    -- Natural
+
+    Hspec.describe "TryCast Natural Word8" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Word16" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Word32" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 4294967295 `Hspec.shouldBe` Just 4294967295
+      test $ f 4294967296 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Word64" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 18446744073709551615 `Hspec.shouldBe` Just 18446744073709551615
+      test $ f 18446744073709551616 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Word" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ let x = maxBound :: Word in hush (Witch.tryCast @Natural.Natural @Word (fromIntegral x)) `Hspec.shouldBe` Just x
+      test $ let x = fromIntegral (maxBound :: Word) + 1 :: Natural.Natural in hush (Witch.tryCast @Natural.Natural @Word x) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Int8" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Int16" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Int32" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f 2147483648 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Int64" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Int.Int64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9223372036854775807 `Hspec.shouldBe` Just 9223372036854775807
+      test $ f 9223372036854775808 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Int" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ let x = maxBound :: Int in hush (Witch.tryCast @Natural.Natural @Int (fromIntegral x)) `Hspec.shouldBe` Just x
+      test $ let x = fromIntegral (maxBound :: Int) + 1 :: Natural.Natural in hush (Witch.tryCast @Natural.Natural @Int x) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Natural Integer" $ do
+      let f = Witch.cast @Natural.Natural @Integer
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 9223372036854775808 `Hspec.shouldBe` 9223372036854775808
+
+    Hspec.describe "TryCast Natural Float" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Float
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Natural Double" $ do
+      let f = hush . Witch.tryCast @Natural.Natural @Double
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+
+    -- Float
+
+    Hspec.describe "TryCast Float Int8" $ do
+      let f = hush . Witch.tryCast @Float @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+      test $ f (-128) `Hspec.shouldBe` Just (-128)
+      test $ f (-129) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Int16" $ do
+      let f = hush . Witch.tryCast @Float @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+      test $ f (-32768) `Hspec.shouldBe` Just (-32768)
+      test $ f (-32769) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Int32" $ do
+      let f = hush . Witch.tryCast @Float @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f (-16777216) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Int64" $ do
+      let f = hush . Witch.tryCast @Float @Int.Int64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f (-16777216) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Int" $ do
+      let f = hush . Witch.tryCast @Float @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f (-16777216) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Integer" $ do
+      let f = hush . Witch.tryCast @Float @Integer
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f (-16777216) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Word8" $ do
+      let f = hush . Witch.tryCast @Float @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Word16" $ do
+      let f = hush . Witch.tryCast @Float @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Word32" $ do
+      let f = hush . Witch.tryCast @Float @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Word64" $ do
+      let f = hush . Witch.tryCast @Float @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Word" $ do
+      let f = hush . Witch.tryCast @Float @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Natural" $ do
+      let f = hush . Witch.tryCast @Float @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f 16777216 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Float Rational" $ do
+      let f = hush . Witch.tryCast @Float @Rational
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f (-0) `Hspec.shouldBe` Just 0
+      test $ f 0.5 `Hspec.shouldBe` Just 0.5
+      test $ f (-0.5) `Hspec.shouldBe` Just (-0.5)
+      test $ f 16777215 `Hspec.shouldBe` Just 16777215
+      test $ f (-16777215) `Hspec.shouldBe` Just (-16777215)
+      test $ f 16777216 `Hspec.shouldBe` Just 16777216
+      test $ f (-16777216) `Hspec.shouldBe` Just (-16777216)
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Float Double" $ do
+      let f = Witch.cast @Float @Double
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 0.5 `Hspec.shouldBe` 0.5
+      test $ f (-0.5) `Hspec.shouldBe` (-0.5)
+      test $ f (0 / 0) `Hspec.shouldSatisfy` isNaN
+      test $ f (1 / 0) `Hspec.shouldBe` (1 / 0)
+      test $ f (-1 / 0) `Hspec.shouldBe` (-1 / 0)
+
+    -- Double
+
+    Hspec.describe "TryCast Double Int8" $ do
+      let f = hush . Witch.tryCast @Double @Int.Int8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 127 `Hspec.shouldBe` Just 127
+      test $ f 128 `Hspec.shouldBe` Nothing
+      test $ f (-128) `Hspec.shouldBe` Just (-128)
+      test $ f (-129) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Int16" $ do
+      let f = hush . Witch.tryCast @Double @Int.Int16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 32767 `Hspec.shouldBe` Just 32767
+      test $ f 32768 `Hspec.shouldBe` Nothing
+      test $ f (-32768) `Hspec.shouldBe` Just (-32768)
+      test $ f (-32769) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Int32" $ do
+      let f = hush . Witch.tryCast @Double @Int.Int32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 2147483647 `Hspec.shouldBe` Just 2147483647
+      test $ f 2147483648 `Hspec.shouldBe` Nothing
+      test $ f (-2147483648) `Hspec.shouldBe` Just (-2147483648)
+      test $ f (-2147483649) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Int64" $ do
+      let f = hush . Witch.tryCast @Double @Int.Int64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (-9007199254740991) `Hspec.shouldBe` Just (-9007199254740991)
+      test $ f (-9007199254740992) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Int" $ do
+      Monad.when (toInteger (maxBound :: Int) < 9007199254740991) untested
+      let f = hush . Witch.tryCast @Double @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (-9007199254740991) `Hspec.shouldBe` Just (-9007199254740991)
+      test $ f (-9007199254740992) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Integer" $ do
+      let f = hush . Witch.tryCast @Double @Integer
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (-9007199254740991) `Hspec.shouldBe` Just (-9007199254740991)
+      test $ f (-9007199254740992) `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Word8" $ do
+      let f = hush . Witch.tryCast @Double @Word.Word8
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 255 `Hspec.shouldBe` Just 255
+      test $ f 256 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Word16" $ do
+      let f = hush . Witch.tryCast @Double @Word.Word16
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 65535 `Hspec.shouldBe` Just 65535
+      test $ f 65536 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Word32" $ do
+      let f = hush . Witch.tryCast @Double @Word.Word32
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 4294967295 `Hspec.shouldBe` Just 4294967295
+      test $ f 4294967296 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Word64" $ do
+      let f = hush . Witch.tryCast @Double @Word.Word64
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Word" $ do
+      Monad.when (toInteger (maxBound :: Word) < 9007199254740991) untested
+      let f = hush . Witch.tryCast @Double @Word
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Natural" $ do
+      let f = hush . Witch.tryCast @Double @Natural.Natural
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f 9007199254740992 `Hspec.shouldBe` Nothing
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "TryCast Double Rational" $ do
+      let f = hush . Witch.tryCast @Double @Rational
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f (-0) `Hspec.shouldBe` Just 0
+      test $ f 0.5 `Hspec.shouldBe` Just 0.5
+      test $ f (-0.5) `Hspec.shouldBe` Just (-0.5)
+      test $ f 9007199254740991 `Hspec.shouldBe` Just 9007199254740991
+      test $ f (-9007199254740991) `Hspec.shouldBe` Just (-9007199254740991)
+      test $ f 9007199254740992 `Hspec.shouldBe` Just 9007199254740992
+      test $ f (-9007199254740992) `Hspec.shouldBe` Just (-9007199254740992)
+      test $ f (0 / 0) `Hspec.shouldBe` Nothing
+      test $ f (1 / 0) `Hspec.shouldBe` Nothing
+      test $ f (-1 / 0) `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Double Float" $ do
+      let f = Witch.cast @Double @Float
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 0.5 `Hspec.shouldBe` 0.5
+      test $ f (-0.5) `Hspec.shouldBe` (-0.5)
+      test $ f (0 / 0) `Hspec.shouldSatisfy` isNaN
+      test $ f (1 / 0) `Hspec.shouldBe` (1 / 0)
+      test $ f (-1 / 0) `Hspec.shouldBe` (-1 / 0)
+
+    -- Ratio
+
+    Hspec.describe "Cast a (Ratio a)" $ do
+      test $ Witch.cast @Integer @Rational 0 `Hspec.shouldBe` 0
+      let f = Witch.cast @Int @(Ratio.Ratio Int)
+      test $ f 0 `Hspec.shouldBe` 0
+
+    Hspec.describe "TryCast (Ratio a) a" $ do
+      test $ hush (Witch.tryCast @Rational @Integer 0) `Hspec.shouldBe` Just 0
+      test $ hush (Witch.tryCast @Rational @Integer 0.5) `Hspec.shouldBe` Nothing
+      let f = hush . Witch.tryCast @(Ratio.Ratio Int) @Int
+      test $ f 0 `Hspec.shouldBe` Just 0
+      test $ f 0.5 `Hspec.shouldBe` Nothing
+
+    Hspec.describe "Cast Rational Float" $ do
+      let f = Witch.cast @Rational @Float
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 0.5 `Hspec.shouldBe` 0.5
+      test $ f (-0.5) `Hspec.shouldBe` (-0.5)
+
+    Hspec.describe "Cast Rational Double" $ do
+      let f = Witch.cast @Rational @Double
+      test $ f 0 `Hspec.shouldBe` 0
+      test $ f 0.5 `Hspec.shouldBe` 0.5
+      test $ f (-0.5) `Hspec.shouldBe` (-0.5)
+
+    -- Fixed
+
+    Hspec.describe "Cast Integer (Fixed a)" $ do
+      test $ Witch.cast @Integer @Fixed.Uni 1 `Hspec.shouldBe` 1
+      let f = Witch.cast @Integer @Fixed.Deci
+      test $ f 1 `Hspec.shouldBe` 0.1
+
+    Hspec.describe "Cast (Fixed a) Integer" $ do
+      test $ Witch.cast @Fixed.Uni @Integer 1 `Hspec.shouldBe` 1
+      let f = Witch.cast @Fixed.Deci @Integer
+      test $ f 1 `Hspec.shouldBe` 10
+
+    -- Complex
+
+    Hspec.describe "Cast a (Complex a)" $ do
+      test $ Witch.cast @Double @(Complex.Complex Double) 1 `Hspec.shouldBe` 1
+      let f = Witch.cast @Float @(Complex.Complex Float)
+      test $ f 1 `Hspec.shouldBe` 1
+
+    Hspec.describe "TryCast (Complex a) a" $ do
+      test $ hush (Witch.tryCast @(Complex.Complex Double) @Double 1) `Hspec.shouldBe` Just 1
+      test $ hush (Witch.tryCast @(Complex.Complex Double) @Double (0 Complex.:+ 1)) `Hspec.shouldBe` Nothing
+      let f = hush . Witch.tryCast @(Complex.Complex Float) @Float
+      test $ f 1 `Hspec.shouldBe` Just 1
+      test $ f (0 Complex.:+ 1) `Hspec.shouldBe` Nothing
+
+    -- NonEmpty
+
+    Hspec.describe "TryCast [a] (NonEmpty a)" $ do
+      let f = hush . Witch.tryCast @[Int] @(NonEmpty.NonEmpty Int)
+      test $ f [] `Hspec.shouldBe` Nothing
+      test $ f [1] `Hspec.shouldBe` Just (1 NonEmpty.:| [])
+      test $ f [1, 2] `Hspec.shouldBe` Just (1 NonEmpty.:| [2])
+
+    Hspec.describe "Cast (NonEmpty a) [a]" $ do
+      let f = Witch.cast @(NonEmpty.NonEmpty Int) @[Int]
+      test $ f (1 NonEmpty.:| []) `Hspec.shouldBe` [1]
+      test $ f (1 NonEmpty.:| [2]) `Hspec.shouldBe` [1, 2]
+
+    -- Set
+
+    Hspec.describe "Cast [a] (Set a)" $ do
+      let f = Witch.cast @[Char] @(Set.Set Char)
+      test $ f [] `Hspec.shouldBe` Set.fromList []
+      test $ f ['a'] `Hspec.shouldBe` Set.fromList ['a']
+      test $ f ['a', 'b'] `Hspec.shouldBe` Set.fromList ['a', 'b']
+      test $ f ['a', 'a'] `Hspec.shouldBe` Set.fromList ['a']
+
+    Hspec.describe "Cast (Set a) [a]" $ do
+      let f = Witch.cast @(Set.Set Char) @[Char]
+      test $ f (Set.fromList []) `Hspec.shouldBe` []
+      test $ f (Set.fromList ['a']) `Hspec.shouldBe` ['a']
+      test $ f (Set.fromList ['a', 'b']) `Hspec.shouldBe` ['a', 'b']
+
+    -- IntSet
+
+    Hspec.describe "Cast [Int] IntSet" $ do
+      let f = Witch.cast @[Int] @IntSet.IntSet
+      test $ f [] `Hspec.shouldBe` IntSet.fromList []
+      test $ f [1] `Hspec.shouldBe` IntSet.fromList [1]
+      test $ f [1, 2] `Hspec.shouldBe` IntSet.fromList [1, 2]
+
+    Hspec.describe "Cast IntSet [Int]" $ do
+      let f = Witch.cast @IntSet.IntSet @[Int]
+      test $ f (IntSet.fromList []) `Hspec.shouldBe` []
+      test $ f (IntSet.fromList [1]) `Hspec.shouldBe` [1]
+      test $ f (IntSet.fromList [1, 2]) `Hspec.shouldBe` [1, 2]
+
+    -- Map
+
+    Hspec.describe "Cast [(k, v)] (Map k v)" $ do
+      let f = Witch.cast @[(Char, Int)] @(Map.Map Char Int)
+      test $ f [] `Hspec.shouldBe` Map.empty
+      test $ f [('a', 1)] `Hspec.shouldBe` Map.fromList [('a', 1)]
+      test $ f [('a', 1), ('b', 2)] `Hspec.shouldBe` Map.fromList [('a', 1), ('b', 2)]
+      test $ f [('a', 1), ('a', 2)] `Hspec.shouldBe` Map.fromList [('a', 2)]
+
+    Hspec.describe "Cast (Map k v) [(k, v)]" $ do
+      let f = Witch.cast @(Map.Map Char Int) @[(Char, Int)]
+      test $ f Map.empty `Hspec.shouldBe` []
+      test $ f (Map.fromList [('a', 1)]) `Hspec.shouldBe` [('a', 1)]
+      test $ f (Map.fromList [('a', 1), ('b', 2)]) `Hspec.shouldBe` [('a', 1), ('b', 2)]
+
+    -- IntMap
+
+    Hspec.describe "Cast [(Int, v)] (IntMap v)" $ do
+      let f = Witch.cast @[(Int, Char)] @(IntMap.IntMap Char)
+      test $ f [] `Hspec.shouldBe` IntMap.fromList []
+      test $ f [(1, 'a')] `Hspec.shouldBe` IntMap.fromList [(1, 'a')]
+      test $ f [(1, 'a'), (2, 'b')] `Hspec.shouldBe` IntMap.fromList [(1, 'a'), (2, 'b')]
+      test $ f [(1, 'a'), (1, 'b')] `Hspec.shouldBe` IntMap.fromList [(1, 'b')]
+
+    Hspec.describe "Cast (IntMap v) [(Int, v)]" $ do
+      let f = Witch.cast @(IntMap.IntMap Char) @[(Int, Char)]
+      test $ f (IntMap.fromList []) `Hspec.shouldBe` []
+      test $ f (IntMap.fromList [(1, 'a')]) `Hspec.shouldBe` [(1, 'a')]
+      test $ f (IntMap.fromList [(1, 'a'), (2, 'b')]) `Hspec.shouldBe` [(1, 'a'), (2, 'b')]
+
+    -- Seq
+
+    Hspec.describe "Cast [a] (Seq a)" $ do
+      let f = Witch.cast @[Int] @(Seq.Seq Int)
+      test $ f [] `Hspec.shouldBe` Seq.fromList []
+      test $ f [1] `Hspec.shouldBe` Seq.fromList [1]
+      test $ f [1, 2] `Hspec.shouldBe` Seq.fromList [1, 2]
+
+    Hspec.describe "Cast (Seq a) [a]" $ do
+      let f = Witch.cast @(Seq.Seq Int) @[Int]
+      test $ f (Seq.fromList []) `Hspec.shouldBe` []
+      test $ f (Seq.fromList [1]) `Hspec.shouldBe` [1]
+      test $ f (Seq.fromList [1, 2]) `Hspec.shouldBe` [1, 2]
+
+    -- ByteString
+
+    Hspec.describe "Cast [Word8] ByteString" $ do
+      let f = Witch.cast @[Word.Word8] @ByteString.ByteString
+      test $ f [] `Hspec.shouldBe` ByteString.pack []
+      test $ f [0x00] `Hspec.shouldBe` ByteString.pack [0x00]
+      test $ f [0x0f, 0xf0] `Hspec.shouldBe` ByteString.pack [0x0f, 0xf0]
+
+    Hspec.describe "Cast ByteString [Word8]" $ do
+      let f = Witch.cast @ByteString.ByteString @[Word.Word8]
+      test $ f (ByteString.pack []) `Hspec.shouldBe` []
+      test $ f (ByteString.pack [0x00]) `Hspec.shouldBe` [0x00]
+      test $ f (ByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` [0x0f, 0xf0]
+
+    Hspec.describe "Cast ByteString LazyByteString" $ do
+      let f = Witch.cast @ByteString.ByteString @LazyByteString.ByteString
+      test $ f (ByteString.pack []) `Hspec.shouldBe` LazyByteString.pack []
+      test $ f (ByteString.pack [0x00]) `Hspec.shouldBe` LazyByteString.pack [0x00]
+      test $ f (ByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` LazyByteString.pack [0x0f, 0xf0]
+
+    Hspec.describe "Cast ByteString ShortByteString" $ do
+      let f = Witch.cast @ByteString.ByteString @ShortByteString.ShortByteString
+      test $ f (ByteString.pack []) `Hspec.shouldBe` ShortByteString.pack []
+      test $ f (ByteString.pack [0x00]) `Hspec.shouldBe` ShortByteString.pack [0x00]
+      test $ f (ByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` ShortByteString.pack [0x0f, 0xf0]
+
+    Hspec.describe "TryCast ByteString Text" $ do
+      let f = hush . Witch.tryCast @ByteString.ByteString @Text.Text
+      test $ f (ByteString.pack []) `Hspec.shouldBe` Just (Text.pack "")
+      test $ f (ByteString.pack [0x61]) `Hspec.shouldBe` Just (Text.pack "a")
+      test $ f (ByteString.pack [0xff]) `Hspec.shouldBe` Nothing
+
+    -- LazyByteString
+
+    Hspec.describe "Cast [Word8] LazyByteString" $ do
+      let f = Witch.cast @[Word.Word8] @LazyByteString.ByteString
+      test $ f [] `Hspec.shouldBe` LazyByteString.pack []
+      test $ f [0x00] `Hspec.shouldBe` LazyByteString.pack [0x00]
+      test $ f [0x0f, 0xf0] `Hspec.shouldBe` LazyByteString.pack [0x0f, 0xf0]
+
+    Hspec.describe "Cast LazyByteString [Word8]" $ do
+      let f = Witch.cast @LazyByteString.ByteString @[Word.Word8]
+      test $ f (LazyByteString.pack []) `Hspec.shouldBe` []
+      test $ f (LazyByteString.pack [0x00]) `Hspec.shouldBe` [0x00]
+      test $ f (LazyByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` [0x0f, 0xf0]
+
+    Hspec.describe "Cast LazyByteString ByteString" $ do
+      let f = Witch.cast @LazyByteString.ByteString @ByteString.ByteString
+      test $ f (LazyByteString.pack []) `Hspec.shouldBe` ByteString.pack []
+      test $ f (LazyByteString.pack [0x00]) `Hspec.shouldBe` ByteString.pack [0x00]
+      test $ f (LazyByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` ByteString.pack [0x0f, 0xf0]
+
+    Hspec.describe "TryCast LazyByteString LazyText" $ do
+      let f = hush . Witch.tryCast @LazyByteString.ByteString @LazyText.Text
+      test $ f (LazyByteString.pack []) `Hspec.shouldBe` Just (LazyText.pack "")
+      test $ f (LazyByteString.pack [0x61]) `Hspec.shouldBe` Just (LazyText.pack "a")
+      test $ f (LazyByteString.pack [0xff]) `Hspec.shouldBe` Nothing
+
+    -- ShortByteString
+
+    Hspec.describe "Cast [Word8] ShortByteString" $ do
+      let f = Witch.cast @[Word.Word8] @ShortByteString.ShortByteString
+      test $ f [] `Hspec.shouldBe` ShortByteString.pack []
+      test $ f [0x00] `Hspec.shouldBe` ShortByteString.pack [0x00]
+      test $ f [0x0f, 0xf0] `Hspec.shouldBe` ShortByteString.pack [0x0f, 0xf0]
+
+    Hspec.describe "Cast ShortByteString [Word8]" $ do
+      let f = Witch.cast @ShortByteString.ShortByteString @[Word.Word8]
+      test $ f (ShortByteString.pack []) `Hspec.shouldBe` []
+      test $ f (ShortByteString.pack [0x00]) `Hspec.shouldBe` [0x00]
+      test $ f (ShortByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` [0x0f, 0xf0]
+
+    Hspec.describe "Cast ShortByteString ByteString" $ do
+      let f = Witch.cast @ShortByteString.ShortByteString @ByteString.ByteString
+      test $ f (ShortByteString.pack []) `Hspec.shouldBe` ByteString.pack []
+      test $ f (ShortByteString.pack [0x00]) `Hspec.shouldBe` ByteString.pack [0x00]
+      test $ f (ShortByteString.pack [0x0f, 0xf0]) `Hspec.shouldBe` ByteString.pack [0x0f, 0xf0]
+
+    -- Text
+
+    Hspec.describe "Cast String Text" $ do
+      let f = Witch.cast @String @Text.Text
+      test $ f "" `Hspec.shouldBe` Text.pack ""
+      test $ f "a" `Hspec.shouldBe` Text.pack "a"
+      test $ f "ab" `Hspec.shouldBe` Text.pack "ab"
+
+    Hspec.describe "Cast Text String" $ do
+      let f = Witch.cast @Text.Text @String
+      test $ f (Text.pack "") `Hspec.shouldBe` ""
+      test $ f (Text.pack "a") `Hspec.shouldBe` "a"
+      test $ f (Text.pack "ab") `Hspec.shouldBe` "ab"
+
+    Hspec.describe "Cast Text LazyText" $ do
+      let f = Witch.cast @Text.Text @LazyText.Text
+      test $ f (Text.pack "") `Hspec.shouldBe` LazyText.pack ""
+      test $ f (Text.pack "a") `Hspec.shouldBe` LazyText.pack "a"
+      test $ f (Text.pack "ab") `Hspec.shouldBe` LazyText.pack "ab"
+
+    Hspec.describe "Cast Text ByteString" $ do
+      let f = Witch.cast @Text.Text @ByteString.ByteString
+      test $ f (Text.pack "") `Hspec.shouldBe` ByteString.pack []
+      test $ f (Text.pack "a") `Hspec.shouldBe` ByteString.pack [0x61]
+
+    -- LazyText
+
+    Hspec.describe "Cast String LazyText" $ do
+      let f = Witch.cast @String @LazyText.Text
+      test $ f "" `Hspec.shouldBe` LazyText.pack ""
+      test $ f "a" `Hspec.shouldBe` LazyText.pack "a"
+      test $ f "ab" `Hspec.shouldBe` LazyText.pack "ab"
+
+    Hspec.describe "Cast LazyText String" $ do
+      let f = Witch.cast @LazyText.Text @String
+      test $ f (LazyText.pack "") `Hspec.shouldBe` ""
+      test $ f (LazyText.pack "a") `Hspec.shouldBe` "a"
+      test $ f (LazyText.pack "ab") `Hspec.shouldBe` "ab"
+
+    Hspec.describe "Cast LazyText Text" $ do
+      let f = Witch.cast @LazyText.Text @Text.Text
+      test $ f (LazyText.pack "") `Hspec.shouldBe` Text.pack ""
+      test $ f (LazyText.pack "a") `Hspec.shouldBe` Text.pack "a"
+      test $ f (LazyText.pack "ab") `Hspec.shouldBe` Text.pack "ab"
+
+    Hspec.describe "Cast LazyText LazyByteString" $ do
+      let f = Witch.cast @LazyText.Text @LazyByteString.ByteString
+      test $ f (LazyText.pack "") `Hspec.shouldBe` LazyByteString.pack []
+      test $ f (LazyText.pack "a") `Hspec.shouldBe` LazyByteString.pack [0x61]
+
+    -- TryCastException
+
+    Hspec.describe "Cast (TryCastException s t0) (TryCastException s t1)" $ do
+      Hspec.it "needs tests" Hspec.pending
+
+    Hspec.describe "Cast (TryCastException s t) String" $ do
+      let f = Witch.cast @(Witch.TryCastException Bool Int) @String
+      test $ f (Witch.TryCastException False Nothing) `Hspec.shouldBe` "TryCastException {- Bool -> Int -} False Nothing"
+
+    Hspec.describe "Cast (TryCastException s t) Text" $ do
+      let f = Witch.cast @(Witch.TryCastException Bool Int) @Text.Text
+      test $ f (Witch.TryCastException False Nothing) `Hspec.shouldBe` Text.pack "TryCastException {- Bool -> Int -} False Nothing"
+
+    Hspec.describe "Cast (TryCastException s t) LazyText" $ do
+      let f = Witch.cast @(Witch.TryCastException Bool Int) @LazyText.Text
+      test $ f (Witch.TryCastException False Nothing) `Hspec.shouldBe` LazyText.pack "TryCastException {- Bool -> Int -} False Nothing"
+
+test :: Hspec.Example a => a -> Hspec.SpecWith (Hspec.Arg a)
+test = Hspec.it ""
+
+untested :: Hspec.SpecWith a
+untested = Hspec.runIO $ Exception.throwIO Untested
+
+hush :: Either x a -> Maybe a
+hush = either (const Nothing) Just
 
 data Untested
   = Untested
diff --git a/witch.cabal b/witch.cabal
--- a/witch.cabal
+++ b/witch.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.2
 
 name: witch
-version: 0.1.1.0
+version: 0.2.0.0
 synopsis: Convert values from one type into another.
 description: Witch converts values from one type into another.
 
