packages feed

witch 1.0.0.3 → 1.0.0.4

raw patch · 11 files changed

+2605/−2437 lines, 11 filesdep +transformersdep ~basedep ~template-haskellPVP ok

version bump matches the API change (PVP)

Dependencies added: transformers

Dependency ranges changed: base, template-haskell

API changes (from Hackage documentation)

Files

README.markdown view
@@ -1,6 +1,6 @@ # Witch -[![CI](https://github.com/tfausak/witch/workflows/CI/badge.svg)](https://github.com/tfausak/witch/actions)+[![CI](https://github.com/tfausak/witch/workflows/Workflow/badge.svg)](https://github.com/tfausak/witch/actions) [![Hackage](https://img.shields.io/hackage/v/witch)](https://hackage.haskell.org/package/witch) [![Stackage](https://www.stackage.org/package/witch/badge/nightly?label=stackage)](https://www.stackage.org/package/witch) 
source/ghc-8.10/Witch/Lift.hs view
@@ -15,16 +15,16 @@ -- > -- > -- Prefer this: -- > $$(liftedFrom @s "some literal")-liftedFrom-  :: forall source target-   . ( TryFrom.TryFrom source target-     , TH.Lift target-     , Show source-     , Typeable.Typeable source-     , Typeable.Typeable target-     )-  => source-  -> TH.Q (TH.TExp target)+liftedFrom ::+  forall source target.+  ( TryFrom.TryFrom source target,+    TH.Lift target,+    Show source,+    Typeable.Typeable source,+    Typeable.Typeable target+  ) =>+  source ->+  TH.Q (TH.TExp target) liftedFrom = TH.liftTyped . Utility.unsafeFrom  -- | This is like 'Utility.unsafeInto' except that it works at compile time@@ -35,14 +35,14 @@ -- > -- > -- Prefer this: -- > $$(liftedInto @t "some literal")-liftedInto-  :: forall target source-   . ( TryFrom.TryFrom source target-     , TH.Lift target-     , Show source-     , Typeable.Typeable source-     , Typeable.Typeable target-     )-  => source-  -> TH.Q (TH.TExp target)+liftedInto ::+  forall target source.+  ( TryFrom.TryFrom source target,+    TH.Lift target,+    Show source,+    Typeable.Typeable source,+    Typeable.Typeable target+  ) =>+  source ->+  TH.Q (TH.TExp target) liftedInto = liftedFrom
source/ghc-8.8/Witch/Lift.hs view
@@ -15,16 +15,16 @@ -- > -- > -- Prefer this: -- > $$(liftedFrom @s "some literal")-liftedFrom-  :: forall source target-   . ( TryFrom.TryFrom source target-     , TH.Lift target-     , Show source-     , Typeable.Typeable source-     , Typeable.Typeable target-     )-  => source-  -> TH.Q (TH.TExp target)+liftedFrom ::+  forall source target.+  ( TryFrom.TryFrom source target,+    TH.Lift target,+    Show source,+    Typeable.Typeable source,+    Typeable.Typeable target+  ) =>+  source ->+  TH.Q (TH.TExp target) liftedFrom s = TH.unsafeTExpCoerce $ TH.lift (Utility.unsafeFrom s :: target)  -- | This is like 'Utility.unsafeInto' except that it works at compile time@@ -35,14 +35,14 @@ -- > -- > -- Prefer this: -- > $$(liftedInto @t "some literal")-liftedInto-  :: forall target source-   . ( TryFrom.TryFrom source target-     , TH.Lift target-     , Show source-     , Typeable.Typeable source-     , Typeable.Typeable target-     )-  => source-  -> TH.Q (TH.TExp target)+liftedInto ::+  forall target source.+  ( TryFrom.TryFrom source target,+    TH.Lift target,+    Show source,+    Typeable.Typeable source,+    Typeable.Typeable target+  ) =>+  source ->+  TH.Q (TH.TExp target) liftedInto = liftedFrom
source/ghc-9.0/Witch/Lift.hs view
@@ -15,17 +15,17 @@ -- > -- > -- Prefer this: -- > $$(liftedFrom @s "some literal")-liftedFrom-  :: forall source target m-   . ( TryFrom.TryFrom source target-     , TH.Lift target-     , Show source-     , Typeable.Typeable source-     , Typeable.Typeable target-     , TH.Quote m-     )-  => source-  -> TH.Code m target+liftedFrom ::+  forall source target m.+  ( TryFrom.TryFrom source target,+    TH.Lift target,+    Show source,+    Typeable.Typeable source,+    Typeable.Typeable target,+    TH.Quote m+  ) =>+  source ->+  TH.Code m target liftedFrom = TH.liftTyped . Utility.unsafeFrom  -- | This is like 'Utility.unsafeInto' except that it works at compile time@@ -36,15 +36,15 @@ -- > -- > -- Prefer this: -- > $$(liftedInto @t "some literal")-liftedInto-  :: forall target source m-   . ( TryFrom.TryFrom source target-     , TH.Lift target-     , Show source-     , Typeable.Typeable source-     , Typeable.Typeable target-     , TH.Quote m-     )-  => source-  -> TH.Code m target+liftedInto ::+  forall target source m.+  ( TryFrom.TryFrom source target,+    TH.Lift target,+    Show source,+    Typeable.Typeable source,+    Typeable.Typeable target,+    TH.Quote m+  ) =>+  source ->+  TH.Code m target liftedInto = liftedFrom
source/library/Witch.hs view
@@ -11,244 +11,254 @@ module Witch   ( -- * Type classes -  -- ** From-    Witch.From.From(from)-  , Witch.Utility.into+    -- ** From+    Witch.From.From (from),+    Witch.Utility.into, -  -- ** TryFrom-  , Witch.TryFrom.TryFrom(tryFrom)-  , Witch.Utility.tryInto+    -- ** TryFrom+    Witch.TryFrom.TryFrom (tryFrom),+    Witch.Utility.tryInto, -  -- * Data types-  , Witch.TryFromException.TryFromException(..)+    -- * Data types+    Witch.TryFromException.TryFromException (..), -  -- * Utilities-  , Witch.Utility.as-  , Witch.Utility.over-  , Witch.Utility.via-  , Witch.Utility.tryVia-  , Witch.Utility.maybeTryFrom-  , Witch.Utility.eitherTryFrom+    -- * Utilities+    Witch.Utility.as,+    Witch.Utility.over,+    Witch.Utility.via,+    Witch.Utility.tryVia,+    Witch.Utility.maybeTryFrom,+    Witch.Utility.eitherTryFrom, -  -- ** Unsafe-  -- | These functions should only be used in two circumstances: When you know-  -- a conversion is safe even though you can't prove it to the compiler, and-  -- when you're alright with your program crashing if the conversion fails.-  -- In all other cases you should prefer the normal conversion functions like-  -- 'Witch.TryFrom.tryFrom'. And if you're converting a literal value,-  -- consider using the Template Haskell conversion functions like-  -- 'Witch.Lift.liftedFrom'.-  , Witch.Utility.unsafeFrom-  , Witch.Utility.unsafeInto+    -- ** Unsafe -  -- ** 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.liftedFrom-  , Witch.Lift.liftedInto+    -- | These functions should only be used in two circumstances: When you know+    -- a conversion is safe even though you can't prove it to the compiler, and+    -- when you're alright with your program crashing if the conversion fails.+    -- In all other cases you should prefer the normal conversion functions like+    -- 'Witch.TryFrom.tryFrom'. And if you're converting a literal value,+    -- consider using the Template Haskell conversion functions like+    -- 'Witch.Lift.liftedFrom'.+    Witch.Utility.unsafeFrom,+    Witch.Utility.unsafeInto, -  -- * Notes+    -- ** Template Haskell -  -- ** Motivation-  -- | Haskell provides many ways to convert between common types, and core-  -- libraries add even more. It can be challenging to know which function to-  -- use when converting from some source type @a@ to some target type @b@. It-  -- can be even harder to know if that conversion is safe or if there are any-  -- pitfalls to watch out for.-  ---  -- This library tries to address that problem by providing a common-  -- interface for converting between types. The 'Witch.From.From' type class-  -- is for conversions that cannot fail, and the 'Witch.TryFrom.TryFrom' type-  -- class is for conversions that can fail. These type classes are inspired-  -- by the [@From@](https://doc.rust-lang.org/std/convert/trait.From.html)-  -- trait in Rust.+    -- | 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.liftedFrom,+    Witch.Lift.liftedInto, -  -- ** Type applications-  -- | Although you can use this library without the [@TypeApplications@](https://downloads.haskell.org/~ghc/9.0.1/docs/html/users_guide/exts/type_applications.html)-  -- language extension, the extension is strongly recommended. Since most-  -- functions provided by this library are polymorphic in at least one type-  -- variable, it's easy to use them in a situation that would be ambiguous.-  -- Normally you could resolve the ambiguity with an explicit type signature,-  -- but type applications are much more ergonomic. For example:-  ---  -- > -- Avoid this:-  -- > f . (from :: Int8 -> Int16) . g-  -- >-  -- > -- Prefer this:-  -- > f . from @Int8 @Int16 . g-  ---  -- Most functions in this library have two versions with their type-  -- variables in opposite orders. That's because usually one side of the-  -- conversion or the other already has its type inferred by context. In-  -- those situations it makes sense to only provide one type argument.-  ---  -- > -- Avoid this: (assuming f :: Int16 -> ...)-  -- > f $ from @Int8 @Int16 0-  -- >-  -- > -- Prefer this:-  -- > f $ from @Int8 0-  ---  -- > -- Avoid this: (assuming x :: Int8)-  -- > g $ from @Int8 @Int16 x-  -- >-  -- > -- Prefer this:-  -- > g $ into @Int16 x+    -- * Notes -  -- ** Alternatives-  -- | Many Haskell libraries already provide similar functionality. How is-  -- this library different?-  ---  -- - [@Coercible@](https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Coerce.html#t:Coercible):-  --   This type class is solved by the compiler, but it only works for types-  --   that have the same runtime representation. This is very convenient for-  --   @newtype@s, but it does not work for converting between arbitrary types-  --   like @Int8@ and @Int16@.-  ---  -- - [@Convertible@](https://hackage.haskell.org/package/convertible-1.1.1.0/docs/Data-Convertible-Base.html#t:Convertible):-  --   This popular conversion type class is similar to what this library-  --   provides. The main difference is that it does not differentiate between-  --   conversions that can fail and those that cannot.-  ---  -- - [@From@](https://hackage.haskell.org/package/basement-0.0.11/docs/Basement-From.html#t:From):-  --   This type class is almost identical to what this library provides.-  --   Unfortunately it is part of the @basement@ package, which is an-  --   alternative standard library that some people may not want to depend-  --   on.-  ---  -- - [@Inj@](https://hackage.haskell.org/package/inj-1.0/docs/Inj.html#t:Inj):-  --   This type class requires instances to be an injection, which means that-  --   no two input values should map to the same output. That restriction-  --   prohibits many useful instances. Also many instances throw impure-  --   exceptions.-  ---  -- In addition to those general-purpose type classes, there are many-  -- alternatives for more specific conversions. How does this library compare-  -- to those?-  ---  -- - Monomorphic conversion functions like [@Data.Text.pack@](https://hackage.haskell.org/package/text-1.2.4.1/docs/Data-Text.html#v:pack)-  --   are explicit but not necessarily convenient. It can be tedious to-  --   manage the imports necessary to use the functions. And if you want to-  --   put them in a custom prelude, you will have to come up with your own-  --   names.-  ---  -- - Polymorphic conversion methods like 'toEnum' are more convenient but-  --   may have unwanted semantics or runtime behavior. For example the 'Enum'-  --   type class is more or less tied to the 'Int' data type and frequently-  --   throws impure exceptions.-  ---  -- - Polymorphic conversion functions like 'fromIntegral' are very-  --   convenient. Unfortunately it can be challenging to know which types-  --   have the instances necessary to make the conversion possible. And even-  --   if the conversion is possible, is it safe? For example converting a-  --   negative 'Int' into a 'Word' will overflow, which may be surprising.+    -- ** Motivation -  -- ** Instances-  -- | When should you add a 'Witch.From.From' (or 'Witch.TryFrom.TryFrom')-  -- instance for some pair of types? This is a surprisingly tricky question-  -- to answer precisely. Instances are driven more by guidelines than rules.-  ---  -- - Conversions must not throw impure exceptions. This means no 'undefined'-  --   or anything equivalent to it.-  ---  -- - Conversions should be unambiguous. If there are multiple reasonable-  --   ways to convert from @a@ to @b@, then you probably should not add a-  --   'Witch.From.From' instance for them.-  ---  -- - Conversions should be lossless. If you have @From a b@ then no two @a@-  --   values should be converted to the same @b@ value.-  ---  --     - Some conversions necessarily lose information, like converting from-  --       a list into a set.-  ---  -- - If you have both @From a b@ and @From b a@, then-  --   @from \@b \@a . from \@a \@b@ should be the same as 'id'. In other-  --   words, @a@ and @b@ are isomorphic.-  ---  --     - This often true, but not always. For example, converting a list-  --       into a set will remove duplicates. And then converting back into a-  --       list will put the elements in ascending order.-  ---  -- - If you have both @From a b@ and @From b c@, then you could also have-  --   @From a c@ and it should be the same as @from \@b \@c . from \@a \@b@.-  --   In other words, @From@ is transitive.-  ---  --     - This is not always true. For example an @Int8@ may be represented-  --       as a number in JSON, whereas an @Int64@ might be represented as a-  --       string. That means @into \@JSON (into \@Int64 int8)@ would not be-  --       the same as @into \@JSON int8@.-  ---  -- - You should not have both a @From@ instance and a @TryFrom@ instance for-  --   the same pair of types.-  ---  -- - If you have a @From@ or @TryFrom@ instance for a pair of types, then-  --   you should probably have a @From@ or @TryFrom@ instance for the same-  --   pair of types but in the opposite direction. In other words if you have-  --   @From a b@ then you should have @From b a@ or @TryFrom b a@.-  ---  -- In general if @s@ /is/ a @t@, then you should add a 'Witch.From.From'-  -- instance for it. But if @s@ merely /can be/ a @t@, then you could add a-  -- 'Witch.TryFrom.TryFrom' instance for it. And if it is technically-  -- possible to convert from @s@ to @t@ but there are a lot of caveats, you-  -- probably should not write any instances at all.+    -- | Haskell provides many ways to convert between common types, and core+    -- libraries add even more. It can be challenging to know which function to+    -- use when converting from some source type @a@ to some target type @b@. It+    -- can be even harder to know if that conversion is safe or if there are any+    -- pitfalls to watch out for.+    --+    -- This library tries to address that problem by providing a common+    -- interface for converting between types. The 'Witch.From.From' type class+    -- is for conversions that cannot fail, and the 'Witch.TryFrom.TryFrom' type+    -- class is for conversions that can fail. These type classes are inspired+    -- by the [@From@](https://doc.rust-lang.org/std/convert/trait.From.html)+    -- trait in Rust. -  -- ** Laws-  -- | As the previous section notes, there aren't any cut and dried laws for-  -- the @From@ and @TryFrom@ type classes. However it can be useful to-  -- consider the following equations for guiding instances:-  ---  -- > -- same strictness-  -- > seq (from @a @b x) y = seq x y-  -- > seq (tryFrom @a @b x) y = seq x y-  ---  -- > -- round trip-  -- > from @b @a (from @a @b x) = x-  ---  -- > -- transitive-  -- > from @b @c (from @a @b x) = from @a @c x-  -- > tryFrom @b @a (from @a @b x) = Right x-  -- > if isRight (tryFrom @a @b x) then-  -- >   fmap (from @b @a) (tryFrom @a @b x) = Right x-  -- > if isRight (tryFrom @a @b x) then do-  -- >   fmap (tryFrom @b @a) (tryFrom @a @b x) = Right (Right x)+    -- ** Type applications -  -- ** Integral types-  -- | There are a lot of types that represent various different ranges of-  -- integers, and Witch may not provide the instances you want. In particular-  -- it does not provide a total way to convert from an @Int32@ into an @Int@.-  -- Why is that?-  ---  -- The Haskell Language Report only demands that @Int@s have at least 30-  -- bits of precision. That means a reasonable Haskell implementation could-  -- have an @Int@ type that's smaller than the @Int32@ type.-  ---  -- However in practice everyone uses the same Haskell implementation: GHC.-  -- And with GHC the @Int@ type always has 32 bits of precision, even on-  -- 32-bit architectures. So for almost everybody, it's probably safe to use-  -- @unsafeFrom \@Int32 \@Int@. Similarly most software these days runs on-  -- machines with 64-bit architectures. That means it's also probably safe-  -- for you to use @unsafeFrom \@Int64 \@Int@.-  ---  -- All of the above also applies for @Word@, @Word32@, and @Word64@.+    -- | Although you can use this library without the [@TypeApplications@](https://downloads.haskell.org/~ghc/9.0.1/docs/html/users_guide/exts/type_applications.html)+    -- language extension, the extension is strongly recommended. Since most+    -- functions provided by this library are polymorphic in at least one type+    -- variable, it's easy to use them in a situation that would be ambiguous.+    -- Normally you could resolve the ambiguity with an explicit type signature,+    -- but type applications are much more ergonomic. For example:+    --+    -- > -- Avoid this:+    -- > f . (from :: Int8 -> Int16) . g+    -- >+    -- > -- Prefer this:+    -- > f . from @Int8 @Int16 . g+    --+    -- Most functions in this library have two versions with their type+    -- variables in opposite orders. That's because usually one side of the+    -- conversion or the other already has its type inferred by context. In+    -- those situations it makes sense to only provide one type argument.+    --+    -- > -- Avoid this: (assuming f :: Int16 -> ...)+    -- > f $ from @Int8 @Int16 0+    -- >+    -- > -- Prefer this:+    -- > f $ from @Int8 0+    --+    -- > -- Avoid this: (assuming x :: Int8)+    -- > g $ from @Int8 @Int16 x+    -- >+    -- > -- Prefer this:+    -- > g $ into @Int16 x -  -- ** Downsides-  -- | As the author of this library, I obviously think that everyone should-  -- use it because it's the greatest thing since sliced bread. But nothing is-  -- perfect, so what are some downsides to this library?-  ---  -- - More specific type classes are often better. For example, @IsString s@-  --   is more useful that @From String s@. The former says that the type @s@-  --   is the same as a string literal, but the latter just says you can-  --   produce a value of type @s@ when given a string.-  ---  -- - The @From@ type class works great for specific pairs of types, but can-  --   get confusing when it's polymorphic. For example if you have some-  --   function with a @From s t@ constraint, that doesn't really tell you-  --   anything about what it's doing.-  ) where+    -- ** Alternatives++    -- | Many Haskell libraries already provide similar functionality. How is+    -- this library different?+    --+    -- - [@Coercible@](https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Coerce.html#t:Coercible):+    --   This type class is solved by the compiler, but it only works for types+    --   that have the same runtime representation. This is very convenient for+    --   @newtype@s, but it does not work for converting between arbitrary types+    --   like @Int8@ and @Int16@.+    --+    -- - [@Convertible@](https://hackage.haskell.org/package/convertible-1.1.1.0/docs/Data-Convertible-Base.html#t:Convertible):+    --   This popular conversion type class is similar to what this library+    --   provides. The main difference is that it does not differentiate between+    --   conversions that can fail and those that cannot.+    --+    -- - [@From@](https://hackage.haskell.org/package/basement-0.0.11/docs/Basement-From.html#t:From):+    --   This type class is almost identical to what this library provides.+    --   Unfortunately it is part of the @basement@ package, which is an+    --   alternative standard library that some people may not want to depend+    --   on.+    --+    -- - [@Inj@](https://hackage.haskell.org/package/inj-1.0/docs/Inj.html#t:Inj):+    --   This type class requires instances to be an injection, which means that+    --   no two input values should map to the same output. That restriction+    --   prohibits many useful instances. Also many instances throw impure+    --   exceptions.+    --+    -- In addition to those general-purpose type classes, there are many+    -- alternatives for more specific conversions. How does this library compare+    -- to those?+    --+    -- - Monomorphic conversion functions like [@Data.Text.pack@](https://hackage.haskell.org/package/text-1.2.4.1/docs/Data-Text.html#v:pack)+    --   are explicit but not necessarily convenient. It can be tedious to+    --   manage the imports necessary to use the functions. And if you want to+    --   put them in a custom prelude, you will have to come up with your own+    --   names.+    --+    -- - Polymorphic conversion methods like 'toEnum' are more convenient but+    --   may have unwanted semantics or runtime behavior. For example the 'Enum'+    --   type class is more or less tied to the 'Int' data type and frequently+    --   throws impure exceptions.+    --+    -- - Polymorphic conversion functions like 'fromIntegral' are very+    --   convenient. Unfortunately it can be challenging to know which types+    --   have the instances necessary to make the conversion possible. And even+    --   if the conversion is possible, is it safe? For example converting a+    --   negative 'Int' into a 'Word' will overflow, which may be surprising.++    -- ** Instances++    -- | When should you add a 'Witch.From.From' (or 'Witch.TryFrom.TryFrom')+    -- instance for some pair of types? This is a surprisingly tricky question+    -- to answer precisely. Instances are driven more by guidelines than rules.+    --+    -- - Conversions must not throw impure exceptions. This means no 'undefined'+    --   or anything equivalent to it.+    --+    -- - Conversions should be unambiguous. If there are multiple reasonable+    --   ways to convert from @a@ to @b@, then you probably should not add a+    --   'Witch.From.From' instance for them.+    --+    -- - Conversions should be lossless. If you have @From a b@ then no two @a@+    --   values should be converted to the same @b@ value.+    --+    --     - Some conversions necessarily lose information, like converting from+    --       a list into a set.+    --+    -- - If you have both @From a b@ and @From b a@, then+    --   @from \@b \@a . from \@a \@b@ should be the same as 'id'. In other+    --   words, @a@ and @b@ are isomorphic.+    --+    --     - This often true, but not always. For example, converting a list+    --       into a set will remove duplicates. And then converting back into a+    --       list will put the elements in ascending order.+    --+    -- - If you have both @From a b@ and @From b c@, then you could also have+    --   @From a c@ and it should be the same as @from \@b \@c . from \@a \@b@.+    --   In other words, @From@ is transitive.+    --+    --     - This is not always true. For example an @Int8@ may be represented+    --       as a number in JSON, whereas an @Int64@ might be represented as a+    --       string. That means @into \@JSON (into \@Int64 int8)@ would not be+    --       the same as @into \@JSON int8@.+    --+    -- - You should not have both a @From@ instance and a @TryFrom@ instance for+    --   the same pair of types.+    --+    -- - If you have a @From@ or @TryFrom@ instance for a pair of types, then+    --   you should probably have a @From@ or @TryFrom@ instance for the same+    --   pair of types but in the opposite direction. In other words if you have+    --   @From a b@ then you should have @From b a@ or @TryFrom b a@.+    --+    -- In general if @s@ /is/ a @t@, then you should add a 'Witch.From.From'+    -- instance for it. But if @s@ merely /can be/ a @t@, then you could add a+    -- 'Witch.TryFrom.TryFrom' instance for it. And if it is technically+    -- possible to convert from @s@ to @t@ but there are a lot of caveats, you+    -- probably should not write any instances at all.++    -- ** Laws++    -- | As the previous section notes, there aren't any cut and dried laws for+    -- the @From@ and @TryFrom@ type classes. However it can be useful to+    -- consider the following equations for guiding instances:+    --+    -- > -- same strictness+    -- > seq (from @a @b x) y = seq x y+    -- > seq (tryFrom @a @b x) y = seq x y+    --+    -- > -- round trip+    -- > from @b @a (from @a @b x) = x+    --+    -- > -- transitive+    -- > from @b @c (from @a @b x) = from @a @c x+    -- > tryFrom @b @a (from @a @b x) = Right x+    -- > if isRight (tryFrom @a @b x) then+    -- >   fmap (from @b @a) (tryFrom @a @b x) = Right x+    -- > if isRight (tryFrom @a @b x) then do+    -- >   fmap (tryFrom @b @a) (tryFrom @a @b x) = Right (Right x)++    -- ** Integral types++    -- | There are a lot of types that represent various different ranges of+    -- integers, and Witch may not provide the instances you want. In particular+    -- it does not provide a total way to convert from an @Int32@ into an @Int@.+    -- Why is that?+    --+    -- The Haskell Language Report only demands that @Int@s have at least 30+    -- bits of precision. That means a reasonable Haskell implementation could+    -- have an @Int@ type that's smaller than the @Int32@ type.+    --+    -- However in practice everyone uses the same Haskell implementation: GHC.+    -- And with GHC the @Int@ type always has 32 bits of precision, even on+    -- 32-bit architectures. So for almost everybody, it's probably safe to use+    -- @unsafeFrom \@Int32 \@Int@. Similarly most software these days runs on+    -- machines with 64-bit architectures. That means it's also probably safe+    -- for you to use @unsafeFrom \@Int64 \@Int@.+    --+    -- All of the above also applies for @Word@, @Word32@, and @Word64@.++    -- ** Downsides++    -- | As the author of this library, I obviously think that everyone should+    -- use it because it's the greatest thing since sliced bread. But nothing is+    -- perfect, so what are some downsides to this library?+    --+    -- - More specific type classes are often better. For example, @IsString s@+    --   is more useful that @From String s@. The former says that the type @s@+    --   is the same as a string literal, but the latter just says you can+    --   produce a value of type @s@ when given a string.+    --+    -- - The @From@ type class works great for specific pairs of types, but can+    --   get confusing when it's polymorphic. For example if you have some+    --   function with a @From s t@ constraint, that doesn't really tell you+    --   anything about what it's doing.+  )+where  import qualified Witch.From import Witch.Instances ()
source/library/Witch/From.hs view
@@ -31,6 +31,5 @@   -- >>> instance From Name String   -- >>> instance From String Name   from :: source -> target-   default from :: Coerce.Coercible source target => source -> target   from = Coerce.coerce
source/library/Witch/Instances.hs view
@@ -1,8 +1,8 @@-{-# OPTIONS_GHC -Wno-orphans #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}+{-# OPTIONS_GHC -Wno-orphans #-}  module Witch.Instances where @@ -201,11 +201,13 @@ -- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215 -- inclusive. instance TryFrom.TryFrom Int.Int32 Float where-  tryFrom = Utility.eitherTryFrom $ \s -> if s < -maxFloat-    then Left Exception.Underflow-    else if s > maxFloat-      then Left Exception.Overflow-      else Right $ fromIntegral s+  tryFrom = Utility.eitherTryFrom $ \s ->+    if s < -maxFloat+      then Left Exception.Underflow+      else+        if s > maxFloat+          then Left Exception.Overflow+          else Right $ fromIntegral s  -- | Uses 'fromIntegral'. instance From.From Int.Int32 Double where@@ -264,20 +266,24 @@ -- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215 -- inclusive. instance TryFrom.TryFrom Int.Int64 Float where-  tryFrom = Utility.eitherTryFrom $ \s -> if s < -maxFloat-    then Left Exception.Underflow-    else if s > maxFloat-      then Left Exception.Overflow-      else Right $ fromIntegral s+  tryFrom = Utility.eitherTryFrom $ \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 TryFrom.TryFrom Int.Int64 Double where-  tryFrom = Utility.eitherTryFrom $ \s -> if s < -maxDouble-    then Left Exception.Underflow-    else if s > maxDouble-      then Left Exception.Overflow-      else Right $ fromIntegral s+  tryFrom = Utility.eitherTryFrom $ \s ->+    if s < -maxDouble+      then Left Exception.Underflow+      else+        if s > maxDouble+          then Left Exception.Overflow+          else Right $ fromIntegral s  -- Int @@ -328,11 +334,13 @@ -- | Uses 'fromIntegral' when the input is between -16,777,215 and 16,777,215 -- inclusive. instance TryFrom.TryFrom Int Float where-  tryFrom = Utility.eitherTryFrom $ \s -> if s < -maxFloat-    then Left Exception.Underflow-    else if s > maxFloat-      then Left Exception.Overflow-      else Right $ fromIntegral s+  tryFrom = Utility.eitherTryFrom $ \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.@@ -340,11 +348,13 @@   tryFrom = Utility.eitherTryFrom $ \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+      else+        if s < -maxDouble+          then Left Exception.Underflow+          else+            if s > maxDouble+              then Left Exception.Overflow+              else Right $ fromIntegral s  -- Integer @@ -394,26 +404,30 @@   -- 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-  tryFrom = Utility.eitherTryFrom-    $ \s -> if s < 0 then Left Exception.Underflow else Right $ fromInteger s+  tryFrom = Utility.eitherTryFrom $+    \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 TryFrom.TryFrom Integer Float where-  tryFrom = Utility.eitherTryFrom $ \s -> if s < -maxFloat-    then Left Exception.Underflow-    else if s > maxFloat-      then Left Exception.Overflow-      else Right $ fromIntegral s+  tryFrom = Utility.eitherTryFrom $ \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 TryFrom.TryFrom Integer Double where-  tryFrom = Utility.eitherTryFrom $ \s -> if s < -maxDouble-    then Left Exception.Underflow-    else if s > maxDouble-      then Left Exception.Overflow-      else Right $ fromIntegral s+  tryFrom = Utility.eitherTryFrom $ \s ->+    if s < -maxDouble+      then Left Exception.Underflow+      else+        if s > maxDouble+          then Left Exception.Overflow+          else Right $ fromIntegral s  -- Word8 @@ -634,9 +648,10 @@ -- | Uses 'fromIntegral' when the input is less than or equal to -- 9,007,199,254,740,991. instance TryFrom.TryFrom Word.Word64 Double where-  tryFrom = Utility.eitherTryFrom $ \s -> if s <= maxDouble-    then Right $ fromIntegral s-    else Left Exception.Overflow+  tryFrom = Utility.eitherTryFrom $ \s ->+    if s <= maxDouble+      then Right $ fromIntegral s+      else Left Exception.Overflow  -- Word @@ -751,9 +766,10 @@ -- | Uses 'fromIntegral' when the input is less than or equal to -- 9,007,199,254,740,991. instance TryFrom.TryFrom Natural.Natural Double where-  tryFrom = Utility.eitherTryFrom $ \s -> if s <= maxDouble-    then Right $ fromIntegral s-    else Left Exception.Overflow+  tryFrom = Utility.eitherTryFrom $ \s ->+    if s <= maxDouble+      then Right $ fromIntegral s+      else Left Exception.Overflow  -- Float @@ -891,9 +907,10 @@  -- | Uses 'Ratio.numerator' when the denominator is 1. instance (Eq a, Num a) => TryFrom.TryFrom (Ratio.Ratio a) a where-  tryFrom = Utility.eitherTryFrom $ \s -> if Ratio.denominator s == 1-    then Right $ Ratio.numerator s-    else Left Exception.LossOfPrecision+  tryFrom = Utility.eitherTryFrom $ \s ->+    if Ratio.denominator s == 1+      then Right $ Ratio.numerator s+      else Left Exception.LossOfPrecision  -- | Uses 'fromRational'. This necessarily loses some precision. instance From.From Rational Float where@@ -906,10 +923,9 @@ -- | Uses `fromRational` as long as there isn't a loss of precision. instance Fixed.HasResolution a => TryFrom.TryFrom Rational (Fixed.Fixed a) where   tryFrom = Utility.eitherTryFrom $ \s ->-    let-      t :: Fixed.Fixed a-      t = fromRational s-    in if toRational t == s then Right t else Left Exception.LossOfPrecision+    let t :: Fixed.Fixed a+        t = fromRational s+     in if toRational t == s then Right t else Left Exception.LossOfPrecision  -- Fixed @@ -935,9 +951,10 @@  -- | Uses 'Complex.realPart' when the imaginary part is 0. instance (Eq a, Num a) => TryFrom.TryFrom (Complex.Complex a) a where-  tryFrom = Utility.eitherTryFrom $ \s -> if Complex.imagPart s == 0-    then Right $ Complex.realPart s-    else Left Exception.LossOfPrecision+  tryFrom = Utility.eitherTryFrom $ \s ->+    if Complex.imagPart s == 0+      then Right $ Complex.realPart s+      else Left Exception.LossOfPrecision  -- NonEmpty @@ -1026,16 +1043,16 @@ -- | Converts via 'Text.Text'. instance TryFrom.TryFrom ByteString.ByteString LazyText.Text where   tryFrom =-    Utility.eitherTryFrom-      $ fmap (Utility.into @LazyText.Text)-      . Utility.tryInto @Text.Text+    Utility.eitherTryFrom $+      fmap (Utility.into @LazyText.Text)+        . Utility.tryInto @Text.Text  -- | Converts via 'Text.Text'. instance TryFrom.TryFrom ByteString.ByteString String where   tryFrom =-    Utility.eitherTryFrom-      $ fmap (Utility.into @String)-      . Utility.tryInto @Text.Text+    Utility.eitherTryFrom $+      fmap (Utility.into @String)+        . Utility.tryInto @Text.Text  -- LazyByteString @@ -1058,16 +1075,16 @@ -- | Converts via 'LazyText.Text'. instance TryFrom.TryFrom LazyByteString.ByteString Text.Text where   tryFrom =-    Utility.eitherTryFrom-      $ fmap (Utility.into @Text.Text)-      . Utility.tryInto @LazyText.Text+    Utility.eitherTryFrom $+      fmap (Utility.into @Text.Text)+        . Utility.tryInto @LazyText.Text  -- | Converts via 'LazyText.Text'. instance TryFrom.TryFrom LazyByteString.ByteString String where   tryFrom =-    Utility.eitherTryFrom-      $ fmap (Utility.into @String)-      . Utility.tryInto @LazyText.Text+    Utility.eitherTryFrom $+      fmap (Utility.into @String)+        . Utility.tryInto @LazyText.Text  -- ShortByteString @@ -1142,9 +1159,10 @@ -- TryFromException  -- | Uses @coerce@.-instance From.From-  (TryFromException.TryFromException source oldTarget)-  (TryFromException.TryFromException source newTarget)+instance+  From.From+    (TryFromException.TryFromException source oldTarget)+    (TryFromException.TryFromException source newTarget)  -- Day @@ -1256,16 +1274,19 @@  -- -realFloatToRational-  :: RealFloat s => s -> Either Exception.ArithException Rational+realFloatToRational ::+  RealFloat s => s -> Either Exception.ArithException Rational realFloatToRational s   | isNaN s = Left Exception.LossOfPrecision-  | isInfinite s = if s > 0-    then Left Exception.Overflow-    else Left Exception.Underflow-  | otherwise = Right $ overPositive-    (uncurry makeRational . uncurry fromDigits . Numeric.floatToDigits 10)-    s+  | isInfinite s =+      if s > 0+        then Left Exception.Overflow+        else Left Exception.Underflow+  | otherwise =+      Right $+        overPositive+          (uncurry makeRational . uncurry fromDigits . Numeric.floatToDigits 10)+          s  overPositive :: (Eq a, Num a, Num b) => (a -> b) -> a -> b overPositive f x = if signum x == -1 then -(f (-x)) else f x@@ -1277,8 +1298,8 @@ makeRational :: Integer -> Integer -> Rational makeRational d e = toRational d * 10 ^^ e -fromNonNegativeIntegral-  :: (Integral s, Num t) => s -> Either Exception.ArithException t+fromNonNegativeIntegral ::+  (Integral s, Num t) => s -> Either Exception.ArithException t fromNonNegativeIntegral x =   if x < 0 then Left Exception.Underflow else Right $ fromIntegral x 
source/library/Witch/TryFromException.hs view
@@ -11,28 +11,32 @@ -- type it was trying to convert into. It also has an optional -- 'Exception.SomeException' for communicating what went wrong while -- converting.-data TryFromException source target = TryFromException-  source-  (Maybe Exception.SomeException)+data TryFromException source target+  = TryFromException+      source+      (Maybe Exception.SomeException)  instance-  ( Show source-  , Typeable.Typeable source-  , Typeable.Typeable target-  ) => Show (TryFromException source target) where+  ( Show source,+    Typeable.Typeable source,+    Typeable.Typeable target+  ) =>+  Show (TryFromException source target)+  where   showsPrec d (TryFromException x e) =-    showParen (d > 10)-      $ showString "TryFromException @"-      . showsPrec 11 (Typeable.typeRep (Proxy.Proxy :: Proxy.Proxy source))-      . showString " @"-      . showsPrec 11 (Typeable.typeRep (Proxy.Proxy :: Proxy.Proxy target))-      . showChar ' '-      . showsPrec 11 x-      . showChar ' '-      . showsPrec 11 e+    showParen (d > 10) $+      showString "TryFromException @"+        . showsPrec 11 (Typeable.typeRep (Proxy.Proxy :: Proxy.Proxy source))+        . showString " @"+        . showsPrec 11 (Typeable.typeRep (Proxy.Proxy :: Proxy.Proxy target))+        . showChar ' '+        . showsPrec 11 x+        . showChar ' '+        . showsPrec 11 e  instance-  ( Show source-  , Typeable.Typeable source-  , Typeable.Typeable target-  ) => Exception.Exception (TryFromException source target)+  ( Show source,+    Typeable.Typeable source,+    Typeable.Typeable target+  ) =>+  Exception.Exception (TryFromException source target)
source/library/Witch/Utility.hs view
@@ -19,7 +19,7 @@ -- > -- > -- Prefer this: -- > f . as @Int . g-as :: forall source . source -> source+as :: forall source. source -> source as = id  -- | This is the same as 'From.from' except that the type variables are in the@@ -30,7 +30,7 @@ -- > -- > -- Prefer this: -- > into @t x-into :: forall target source . From.From source target => source -> target+into :: forall target source. From.From source target => source -> target into = From.from  -- | This function converts from some @source@ type into some @target@ type,@@ -43,12 +43,12 @@ -- > -- > -- Prefer this: -- > over @t f-over-  :: forall target source-   . (From.From source target, From.From target source)-  => (target -> target)-  -> source-  -> source+over ::+  forall target source.+  (From.From source target, From.From target source) =>+  (target -> target) ->+  source ->+  source over f = From.from . f . From.from  -- | This function first converts from some @source@ type into some @through@@@ -61,11 +61,11 @@ -- > -- > -- Prefer this: -- > via @u-via-  :: forall through source target-   . (From.From source through, From.From through target)-  => source-  -> target+via ::+  forall through source target.+  (From.From source through, From.From through target) =>+  source ->+  target via = From.from . (\x -> x :: through) . From.from  -- | This is the same as 'TryFrom.tryFrom' except that the type variables are@@ -76,11 +76,11 @@ -- > -- > -- Prefer this: -- > tryInto @t x-tryInto-  :: forall target source-   . TryFrom.TryFrom source target-  => source-  -> Either (TryFromException.TryFromException source target) target+tryInto ::+  forall target source.+  TryFrom.TryFrom source target =>+  source ->+  Either (TryFromException.TryFromException source target) target tryInto = TryFrom.tryFrom  -- | This is similar to 'via' except that it works with 'TryFrom.TryFrom'@@ -96,11 +96,11 @@ -- > -- > -- Prefer this: -- > tryVia @u-tryVia-  :: forall through source target-   . (TryFrom.TryFrom source through, TryFrom.TryFrom through target)-  => source-  -> Either (TryFromException.TryFromException source target) target+tryVia ::+  forall through source target.+  (TryFrom.TryFrom source through, TryFrom.TryFrom through target) =>+  source ->+  Either (TryFromException.TryFromException source target) target tryVia s = case TryFrom.tryFrom s of   Left e -> Left $ withTarget e   Right u -> case TryFrom.tryFrom (u :: through) of@@ -117,10 +117,10 @@ -- > -- > -- Prefer this: -- > tryFrom = maybeTryFrom f-maybeTryFrom-  :: (source -> Maybe target)-  -> source-  -> Either (TryFromException.TryFromException source target) target+maybeTryFrom ::+  (source -> Maybe target) ->+  source ->+  Either (TryFromException.TryFromException source target) target maybeTryFrom f s = case f s of   Nothing -> Left $ TryFromException.TryFromException s Nothing   Just t -> Right t@@ -135,11 +135,11 @@ -- > -- > -- Prefer this: -- > tryFrom = eitherTryFrom f-eitherTryFrom-  :: Exception.Exception exception-  => (source -> Either exception target)-  -> source-  -> Either (TryFromException.TryFromException source target) target+eitherTryFrom ::+  Exception.Exception exception =>+  (source -> Either exception target) ->+  source ->+  Either (TryFromException.TryFromException source target) target eitherTryFrom f s = case f s of   Left e ->     Left . TryFromException.TryFromException s . Just $ Exception.toException e@@ -153,16 +153,16 @@ -- > -- > -- Prefer this: -- > unsafeFrom @s-unsafeFrom-  :: forall source target-   . ( Stack.HasCallStack-     , TryFrom.TryFrom source target-     , Show source-     , Typeable.Typeable source-     , Typeable.Typeable target-     )-  => source-  -> target+unsafeFrom ::+  forall source target.+  ( Stack.HasCallStack,+    TryFrom.TryFrom source target,+    Show source,+    Typeable.Typeable source,+    Typeable.Typeable target+  ) =>+  source ->+  target unsafeFrom = either Exception.throw id . TryFrom.tryFrom  -- | This function is like 'tryInto' except that it will throw an impure@@ -173,27 +173,27 @@ -- > -- > -- Prefer this: -- > unsafeInto @t-unsafeInto-  :: forall target source-   . ( Stack.HasCallStack-     , TryFrom.TryFrom source target-     , Show source-     , Typeable.Typeable source-     , Typeable.Typeable target-     )-  => source-  -> target+unsafeInto ::+  forall target source.+  ( Stack.HasCallStack,+    TryFrom.TryFrom source target,+    Show source,+    Typeable.Typeable source,+    Typeable.Typeable target+  ) =>+  source ->+  target unsafeInto = unsafeFrom -withSource-  :: newSource-  -> TryFromException.TryFromException oldSource target-  -> TryFromException.TryFromException newSource target+withSource ::+  newSource ->+  TryFromException.TryFromException oldSource target ->+  TryFromException.TryFromException newSource target withSource x (TryFromException.TryFromException _ e) =   TryFromException.TryFromException x e -withTarget-  :: forall newTarget source oldTarget-   . TryFromException.TryFromException source oldTarget-  -> TryFromException.TryFromException source newTarget+withTarget ::+  forall newTarget source oldTarget.+  TryFromException.TryFromException source oldTarget ->+  TryFromException.TryFromException source newTarget withTarget = Coerce.coerce
source/test-suite/Main.hs view
@@ -1,1981 +1,2117 @@-{-# OPTIONS_GHC -Wno-error=overflowed-literals #-}--{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NegativeLiterals #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeApplications #-}--import qualified Control.Exception as Exception-import qualified Data.ByteString as ByteString-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.Time as Time-import qualified Data.Time.Clock.POSIX as Time-import qualified Data.Time.Clock.System as Time-import qualified Data.Time.Clock.TAI as Time-import qualified Data.Word as Word-import qualified Numeric.Natural as Natural-import Test.HUnit (Test(TestCase), assertBool, runTestTTAndExit, (~:), (~?=))-import qualified Witch--main :: IO ()-main =-  runTestTTAndExit-    $ "Witch"-    ~: [ "From"-         ~: ["from" ~: [Witch.from (1 :: Int.Int8) ~?= (1 :: Int.Int16)]]-       , "TryFrom"-         ~: [ "tryFrom"-                ~: let f = hush . Witch.tryFrom @Int.Int16 @Int.Int8-                   in [f 1 ~?= Just 1, f 128 ~?= Nothing]-            ]-       , "Utility"-         ~: [ "as" ~: [Witch.as @Int.Int8 1 ~?= 1]-            , "from" ~: [Witch.from @Int.Int8 1 ~?= (1 :: Int.Int16)]-            , "into" ~: [Witch.into @Int.Int16 (1 :: Int.Int8) ~?= 1]-            , "over" ~: [Witch.over @Int.Int8 (+ 1) (Age 1) ~?= Age 2]-            , "via"-              ~: [Witch.via @Int.Int16 (1 :: Int.Int8) ~?= (1 :: Int.Int32)]-            , "tryFrom"-              ~: [hush (Witch.tryFrom @Int.Int16 1) ~?= Just (1 :: Int.Int8)]-            , "tryInto"-              ~: [hush (Witch.tryInto @Int.Int8 (1 :: Int.Int16)) ~?= Just 1]-            , "tryVia"-              ~: let f = Witch.tryVia @Int.Int16 @Int.Int32 @Int.Int8-                 in-                   [ hush (f 1) ~?= Just 1-                   , hush (f 128) ~?= Nothing-                   , hush (f 32768) ~?= Nothing-                   ]-            , "unsafeFrom"-              ~: let f = Witch.unsafeFrom @Int.Int16 @Int.Int8-                 in-                   [ f 1 ~?= 1-                   , TestCase $ do-                     result <--                       Exception.try @Exception.SomeException-                       . Exception.evaluate-                       $ f 128-                     assertBool (show result) $ Either.isLeft result-                   ]-            , "unsafeInto"-              ~: [Witch.unsafeInto @Int.Int8 (1 :: Int.Int16) ~?= 1]-            ]-       , "Lift"-         ~: [ "liftedFrom"-              ~: [($$(Witch.liftedFrom (1 :: Int.Int16)) :: Int.Int8) ~?= 1]-            , "liftedInto"-              ~: [$$(Witch.liftedInto @Int.Int8 (1 :: Int.Int16)) ~?= 1]-            ]-       , "TryFromException"-         ~: [ "show"-                ~: [ show (Witch.TryFromException @Int @Int 0 Nothing)-                     ~?= "TryFromException @Int @Int 0 Nothing"-                   , show-                       (Witch.TryFromException @(Seq.Seq Int) @(Seq.Seq Int)-                         (Seq.fromList [])-                         (Just (Exception.toException Exception.Overflow))-                       )-                     ~?= "TryFromException @(Seq Int) @(Seq Int) (fromList []) (Just arithmetic overflow)"-                   ]-            ]-       , "Instances"-         ~: [ "From a a" ~: let f = Witch.from @Int @Int in [f 0 ~?= 0]--    -- Int8-            , "From Int8 Int16"-              ~: let f = Witch.from @Int.Int8 @Int.Int16-                 in [f 0 ~?= 0, f 127 ~?= 127, f (-128) ~?= (-128)]-            , "From Int8 Int32"-              ~: let f = Witch.from @Int.Int8 @Int.Int32-                 in [f 0 ~?= 0, f 127 ~?= 127, f (-128) ~?= (-128)]-            , "From Int8 Int64"-              ~: let f = Witch.from @Int.Int8 @Int.Int64-                 in [f 0 ~?= 0, f 127 ~?= 127, f (-128) ~?= (-128)]-            , "From Int8 Int"-              ~: let f = Witch.from @Int.Int8 @Int-                 in [f 0 ~?= 0, f 127 ~?= 127, f (-128) ~?= (-128)]-            , "From Int8 Integer"-              ~: let f = Witch.from @Int.Int8 @Integer-                 in [f 0 ~?= 0, f 127 ~?= 127, f (-128) ~?= (-128)]-            , "TryFrom Int8 Word8"-              ~: let f = hush . Witch.tryFrom @Int.Int8 @Word.Word8-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f (-1) ~?= Nothing]-            , "TryFrom Int8 Word16"-              ~: let f = hush . Witch.tryFrom @Int.Int8 @Word.Word16-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f (-1) ~?= Nothing]-            , "TryFrom Int8 Word32"-              ~: let f = hush . Witch.tryFrom @Int.Int8 @Word.Word32-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f (-1) ~?= Nothing]-            , "TryFrom Int8 Word64"-              ~: let f = hush . Witch.tryFrom @Int.Int8 @Word.Word64-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f (-1) ~?= Nothing]-            , "TryFrom Int8 Word"-              ~: let f = hush . Witch.tryFrom @Int.Int8 @Word-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f (-1) ~?= Nothing]-            , "TryFrom Int8 Natural"-              ~: let f = hush . Witch.tryFrom @Int.Int8 @Natural.Natural-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f (-1) ~?= Nothing]-            , "From Int8 Float"-              ~: let f = Witch.from @Int.Int8 @Float-                 in [f 0 ~?= 0, f 127 ~?= 127, f (-128) ~?= (-128)]-            , "From Int8 Double"-              ~: let f = Witch.from @Int.Int8 @Double-                 in [f 0 ~?= 0, f 127 ~?= 127, f (-128) ~?= (-128)]--    -- Int16-            , "TryFrom Int16 Int8"-              ~: let f = hush . Witch.tryFrom @Int.Int16 @Int.Int8-                 in-                   [ f 0 ~?= Just 0-                   , f 127 ~?= Just 127-                   , f 128 ~?= Nothing-                   , f (-128) ~?= Just (-128)-                   , f (-129) ~?= Nothing-                   ]-            , "From Int16 Int32"-              ~: let f = Witch.from @Int.Int16 @Int.Int32-                 in [f 0 ~?= 0, f 32767 ~?= 32767, f (-32768) ~?= (-32768)]-            , "From Int16 Int64"-              ~: let f = Witch.from @Int.Int16 @Int.Int64-                 in [f 0 ~?= 0, f 32767 ~?= 32767, f (-32768) ~?= (-32768)]-            , "From Int16 Int"-              ~: let f = Witch.from @Int.Int16 @Int-                 in [f 0 ~?= 0, f 32767 ~?= 32767, f (-32768) ~?= (-32768)]-            , "From Int16 Integer"-              ~: let f = Witch.from @Int.Int16 @Integer-                 in [f 0 ~?= 0, f 32767 ~?= 32767, f (-32768) ~?= (-32768)]-            , "TryFrom Int16 Word8"-              ~: let f = hush . Witch.tryFrom @Int.Int16 @Word.Word8-                 in-                   [ f 0 ~?= Just 0-                   , f 255 ~?= Just 255-                   , f 256 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int16 Word16"-              ~: let f = hush . Witch.tryFrom @Int.Int16 @Word.Word16-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f (-1) ~?= Nothing]-            , "TryFrom Int16 Word32"-              ~: let f = hush . Witch.tryFrom @Int.Int16 @Word.Word32-                 in-                   [f 0 ~?= Just 0, f 32767 ~?= Just 32767, f (-1) ~?= Nothing]-            , "TryFrom Int16 Word64"-              ~: let f = hush . Witch.tryFrom @Int.Int16 @Word.Word64-                 in-                   [f 0 ~?= Just 0, f 32767 ~?= Just 32767, f (-1) ~?= Nothing]-            , "TryFrom Int16 Word"-              ~: let f = hush . Witch.tryFrom @Int.Int16 @Word-                 in-                   [f 0 ~?= Just 0, f 32767 ~?= Just 32767, f (-1) ~?= Nothing]-            , "TryFrom Int16 Natural"-              ~: let f = hush . Witch.tryFrom @Int.Int16 @Natural.Natural-                 in-                   [f 0 ~?= Just 0, f 32767 ~?= Just 32767, f (-1) ~?= Nothing]-            , "From Int16 Float"-              ~: let f = Witch.from @Int.Int16 @Float-                 in [f 0 ~?= 0, f 32767 ~?= 32767, f (-32768) ~?= (-32768)]-            , "From Int16 Double"-              ~: let f = Witch.from @Int.Int16 @Double-                 in [f 0 ~?= 0, f 32767 ~?= 32767, f (-32768) ~?= (-32768)]--    -- Int32-            , "TryFrom Int32 Int8"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Int.Int8-                 in-                   [ f 0 ~?= Just 0-                   , f 127 ~?= Just 127-                   , f 128 ~?= Nothing-                   , f (-128) ~?= Just (-128)-                   , f (-129) ~?= Nothing-                   ]-            , "TryFrom Int32 Int16"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   , f (-32768) ~?= Just (-32768)-                   , f (-32769) ~?= Nothing-                   ]-            , "From Int32 Int64"-              ~: let f = Witch.from @Int.Int32 @Int.Int64-                 in-                   [ f 0 ~?= 0-                   , f 2147483647 ~?= 2147483647-                   , f (-2147483648) ~?= (-2147483648)-                   ]-            , "TryFrom Int32 Int"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Int-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f (-2147483648) ~?= Just (-2147483648)-                   ]-            , "From Int32 Integer"-              ~: let f = Witch.from @Int.Int32 @Integer-                 in-                   [ f 0 ~?= 0-                   , f 2147483647 ~?= 2147483647-                   , f (-2147483648) ~?= (-2147483648)-                   ]-            , "TryFrom Int32 Word8"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Word.Word8-                 in-                   [ f 0 ~?= Just 0-                   , f 255 ~?= Just 255-                   , f 256 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int32 Word16"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int32 Word32"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int32 Word64"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Word.Word64-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int32 Word"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Word-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int32 Natural"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Natural.Natural-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int32 Float"-              ~: let f = hush . Witch.tryFrom @Int.Int32 @Float-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (-16777215) ~?= Just (-16777215)-                   , f (-16777216) ~?= Nothing-                   ]-            , "From Int32 Double"-              ~: let f = Witch.from @Int.Int32 @Double-                 in-                   [ f 0 ~?= 0-                   , f 2147483647 ~?= 2147483647-                   , f (-2147483648) ~?= (-2147483648)-                   ]--    -- Int64-            , "TryFrom Int64 Int8"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Int.Int8-                 in-                   [ f 0 ~?= Just 0-                   , f 127 ~?= Just 127-                   , f 128 ~?= Nothing-                   , f (-128) ~?= Just (-128)-                   , f (-129) ~?= Nothing-                   ]-            , "TryFrom Int64 Int16"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   , f (-32768) ~?= Just (-32768)-                   , f (-32769) ~?= Nothing-                   ]-            , "TryFrom Int64 Int32"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f 2147483648 ~?= Nothing-                   , f (-2147483648) ~?= Just (-2147483648)-                   , f (-2147483649) ~?= Nothing-                   ]-            , "TryFrom Int64 Int"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Int-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int-                     in-                       if toInteger x >= 9223372036854775807-                         then f 9223372036854775807-                           ~?= Just 9223372036854775807-                         else f (fromIntegral x) ~?= Just x-                   , let x = minBound :: Int-                     in-                       if toInteger x <= (-9223372036854775808)-                         then f (-9223372036854775808)-                           ~?= Just (-9223372036854775808)-                         else f (fromIntegral x) ~?= Just x-                   ]-            , "From Int64 Integer"-              ~: let f = Witch.from @Int.Int64 @Integer-                 in-                   [ f 0 ~?= 0-                   , f 9223372036854775807 ~?= 9223372036854775807-                   , f (-9223372036854775808) ~?= (-9223372036854775808)-                   ]-            , "TryFrom Int64 Word8"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Word.Word8-                 in-                   [ f 0 ~?= Just 0-                   , f 255 ~?= Just 255-                   , f 256 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int64 Word16"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int64 Word32"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int64 Word64"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Word.Word64-                 in-                   [ f 0 ~?= Just 0-                   , f 9223372036854775807 ~?= Just 9223372036854775807-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int64 Word"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Word-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Word-                     in-                       if toInteger x >= 9223372036854775807-                         then f 9223372036854775807-                           ~?= Just 9223372036854775807-                         else f (fromIntegral x) ~?= Just x-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int64 Natural"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Natural.Natural-                 in-                   [ f 0 ~?= Just 0-                   , f 9223372036854775807 ~?= Just 9223372036854775807-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int64 Float"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Float-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (-16777215) ~?= Just (-16777215)-                   , f (-16777216) ~?= Nothing-                   ]-            , "TryFrom Int64 Double"-              ~: let f = hush . Witch.tryFrom @Int.Int64 @Double-                 in-                   [ f 0 ~?= Just 0-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f 9007199254740992 ~?= Nothing-                   , f (-9007199254740991) ~?= Just (-9007199254740991)-                   , f (-9007199254740992) ~?= Nothing-                   ]--    -- Int-            , "TryFrom Int Int8"-              ~: let f = hush . Witch.tryFrom @Int @Int.Int8-                 in-                   [ f 0 ~?= Just 0-                   , f 127 ~?= Just 127-                   , f 128 ~?= Nothing-                   , f (-128) ~?= Just (-128)-                   , f (-129) ~?= Nothing-                   ]-            , "TryFrom Int Int16"-              ~: let f = hush . Witch.tryFrom @Int @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   , f (-32768) ~?= Just (-32768)-                   , f (-32769) ~?= Nothing-                   ]-            , "TryFrom Int Int32"-              ~: let f = hush . Witch.tryFrom @Int @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , let x = maxBound :: Int-                     in-                       if toInteger x >= 2147483648-                         then f 2147483648 ~?= Nothing-                         else f x ~?= Just (fromIntegral x)-                   , f (-2147483648) ~?= Just (-2147483648)-                   , let x = minBound :: Int-                     in-                       if toInteger x <= (-2147483649)-                         then f (-2147483649) ~?= Nothing-                         else f x ~?= Just (fromIntegral x)-                   ]-            , "From Int Int64"-              ~: let f = Witch.from @Int @Int.Int64-                 in-                   [ f 0 ~?= 0-                   , f maxBound ~?= fromIntegral (maxBound :: Int)-                   , f minBound ~?= fromIntegral (minBound :: Int)-                   ]-            , "From Int Integer"-              ~: let f = Witch.from @Int @Integer-                 in-                   [ f 0 ~?= 0-                   , f maxBound ~?= fromIntegral (maxBound :: Int)-                   , f minBound ~?= fromIntegral (minBound :: Int)-                   ]-            , "TryFrom Int Word8"-              ~: let f = hush . Witch.tryFrom @Int @Word.Word8-                 in-                   [ f 0 ~?= Just 0-                   , f 255 ~?= Just 255-                   , f 256 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int Word16"-              ~: let f = hush . Witch.tryFrom @Int @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int Word32"-              ~: let f = hush . Witch.tryFrom @Int @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int-                     in-                       if toInteger x >= 4294967295-                         then f 4294967295 ~?= Just 4294967295-                         else f x ~?= Just (fromIntegral x)-                   , let x = maxBound :: Int-                     in-                       if toInteger x >= 4294967296-                         then f 4294967296 ~?= Nothing-                         else f x ~?= Just (fromIntegral x)-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int Word64"-              ~: let f = hush . Witch.tryFrom @Int @Word.Word64-                 in-                   [ f 0 ~?= Just 0-                   , f maxBound ~?= Just (fromIntegral (maxBound :: Int))-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int Word"-              ~: let f = hush . Witch.tryFrom @Int @Word-                 in-                   [ f 0 ~?= Just 0-                   , f maxBound ~?= Just (fromIntegral (maxBound :: Int))-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int Natural"-              ~: let f = hush . Witch.tryFrom @Int @Natural.Natural-                 in-                   [ f 0 ~?= Just 0-                   , f maxBound ~?= Just (fromIntegral (maxBound :: Int))-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Int Float"-              ~: let f = hush . Witch.tryFrom @Int @Float-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (-16777215) ~?= Just (-16777215)-                   , f (-16777216) ~?= Nothing-                   ]-            , "TryFrom Int Double"-              ~: let f = hush . Witch.tryFrom @Int @Double-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int-                     in-                       if toInteger x >= 9007199254740991-                         then f 9007199254740991 ~?= Just 9007199254740991-                         else f x ~?= Just (fromIntegral x)-                   , let x = maxBound :: Int-                     in-                       if toInteger x >= 9007199254740992-                         then f 9007199254740992 ~?= Nothing-                         else f x ~?= Just (fromIntegral x)-                   , let x = minBound :: Int-                     in-                       if toInteger x <= (-9007199254740991)-                         then f (-9007199254740991)-                           ~?= Just (-9007199254740991)-                         else f x ~?= Just (fromIntegral x)-                   , let x = minBound :: Int-                     in-                       if toInteger x <= (-9007199254740992)-                         then f (-9007199254740992) ~?= Nothing-                         else f x ~?= Just (fromIntegral x)-                   ]--    -- Integer-            , "TryFrom Integer Int8"-              ~: let f = hush . Witch.tryFrom @Integer @Int.Int8-                 in-                   [ f 0 ~?= Just 0-                   , f 127 ~?= Just 127-                   , f 128 ~?= Nothing-                   , f (-128) ~?= Just (-128)-                   , f (-129) ~?= Nothing-                   ]-            , "TryFrom Integer Int16"-              ~: let f = hush . Witch.tryFrom @Integer @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   , f (-32768) ~?= Just (-32768)-                   , f (-32769) ~?= Nothing-                   ]-            , "TryFrom Integer Int32"-              ~: let f = hush . Witch.tryFrom @Integer @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f 2147483648 ~?= Nothing-                   , f (-2147483648) ~?= Just (-2147483648)-                   , f (-2147483649) ~?= Nothing-                   ]-            , "TryFrom Integer Int64"-              ~: let f = hush . Witch.tryFrom @Integer @Int.Int64-                 in-                   [ f 0 ~?= Just 0-                   , f 9223372036854775807 ~?= Just 9223372036854775807-                   , f 9223372036854775808 ~?= Nothing-                   , f (-9223372036854775808) ~?= Just (-9223372036854775808)-                   , f (-9223372036854775809) ~?= Nothing-                   ]-            , "TryFrom Integer Int"-              ~: let f = hush . Witch.tryFrom @Integer @Int-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int in f (fromIntegral x) ~?= Just x-                   , let x = toInteger (maxBound :: Int) + 1-                     in f x ~?= Nothing-                   , let x = minBound :: Int in f (fromIntegral x) ~?= Just x-                   , let x = toInteger (minBound :: Int) - 1-                     in f x ~?= Nothing-                   ]-            , "TryFrom Integer Word8"-              ~: let f = hush . Witch.tryFrom @Integer @Word.Word8-                 in-                   [ f 0 ~?= Just 0-                   , f 255 ~?= Just 255-                   , f 256 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Integer Word16"-              ~: let f = hush . Witch.tryFrom @Integer @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Integer Word32"-              ~: let f = hush . Witch.tryFrom @Integer @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , f 4294967295 ~?= Just 4294967295-                   , f 4294967296 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Integer Word64"-              ~: let f = hush . Witch.tryFrom @Integer @Word.Word64-                 in-                   [ f 0 ~?= Just 0-                   , f 18446744073709551615 ~?= Just 18446744073709551615-                   , f 18446744073709551616 ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Integer Word"-              ~: let f = hush . Witch.tryFrom @Integer @Word-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Word in f (fromIntegral x) ~?= Just x-                   , let x = toInteger (maxBound :: Word) + 1-                     in f x ~?= Nothing-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Integer Natural"-              ~: let f = hush . Witch.tryFrom @Integer @Natural.Natural-                 in-                   [ f 0 ~?= Just 0-                   , f 18446744073709551616 ~?= Just 18446744073709551616-                   , f (-1) ~?= Nothing-                   ]-            , "TryFrom Integer Float"-              ~: let f = hush . Witch.tryFrom @Integer @Float-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (-16777215) ~?= Just (-16777215)-                   , f (-16777216) ~?= Nothing-                   ]-            , "TryFrom Integer Double"-              ~: let f = hush . Witch.tryFrom @Integer @Double-                 in-                   [ f 0 ~?= Just 0-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f 9007199254740992 ~?= Nothing-                   , f (-9007199254740991) ~?= Just (-9007199254740991)-                   , f (-9007199254740992) ~?= Nothing-                   ]--    -- Word8-            , "From Word8 Word16"-              ~: let f = Witch.from @Word.Word8 @Word.Word16-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Word32"-              ~: let f = Witch.from @Word.Word8 @Word.Word32-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Word64"-              ~: let f = Witch.from @Word.Word8 @Word.Word64-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Word"-              ~: let f = Witch.from @Word.Word8 @Word-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Natural"-              ~: let f = Witch.from @Word.Word8 @Natural.Natural-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "TryFrom Word8 Int8"-              ~: let f = hush . Witch.tryFrom @Word.Word8 @Int.Int8-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f 128 ~?= Nothing]-            , "From Word8 Int16"-              ~: let f = Witch.from @Word.Word8 @Int.Int16-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Int32"-              ~: let f = Witch.from @Word.Word8 @Int.Int32-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Int64"-              ~: let f = Witch.from @Word.Word8 @Int.Int64-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Int"-              ~: let f = Witch.from @Word.Word8 @Int-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Integer"-              ~: let f = Witch.from @Word.Word8 @Integer-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Float"-              ~: let f = Witch.from @Word.Word8 @Float-                 in [f 0 ~?= 0, f 255 ~?= 255]-            , "From Word8 Double"-              ~: let f = Witch.from @Word.Word8 @Double-                 in [f 0 ~?= 0, f 255 ~?= 255]--    -- Word16-            , "TryFrom Word16 Word8"-              ~: let f = hush . Witch.tryFrom @Word.Word16 @Word.Word8-                 in [f 0 ~?= Just 0, f 255 ~?= Just 255, f 256 ~?= Nothing]-            , "From Word16 Word32"-              ~: let f = Witch.from @Word.Word16 @Word.Word32-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "From Word16 Word64"-              ~: let f = Witch.from @Word.Word16 @Word.Word64-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "From Word16 Word"-              ~: let f = Witch.from @Word.Word16 @Word-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "From Word16 Natural"-              ~: let f = Witch.from @Word.Word16 @Natural.Natural-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "TryFrom Word16 Int8"-              ~: let f = hush . Witch.tryFrom @Word.Word16 @Int.Int8-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f 128 ~?= Nothing]-            , "TryFrom Word16 Int16"-              ~: let f = hush . Witch.tryFrom @Word.Word16 @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   ]-            , "From Word16 Int32"-              ~: let f = Witch.from @Word.Word16 @Int.Int32-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "From Word16 Int64"-              ~: let f = Witch.from @Word.Word16 @Int.Int64-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "From Word16 Int"-              ~: let f = Witch.from @Word.Word16 @Int-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "From Word16 Integer"-              ~: let f = Witch.from @Word.Word16 @Integer-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "From Word16 Float"-              ~: let f = Witch.from @Word.Word16 @Float-                 in [f 0 ~?= 0, f 65535 ~?= 65535]-            , "From Word16 Double"-              ~: let f = Witch.from @Word.Word16 @Double-                 in [f 0 ~?= 0, f 65535 ~?= 65535]--    -- Word32-            , "TryFrom Word32 Word8"-              ~: let f = hush . Witch.tryFrom @Word.Word32 @Word.Word8-                 in [f 0 ~?= Just 0, f 255 ~?= Just 255, f 256 ~?= Nothing]-            , "TryFrom Word32 Word16"-              ~: let f = hush . Witch.tryFrom @Word.Word32 @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   ]-            , "From Word32 Word64"-              ~: let f = Witch.from @Word.Word32 @Word.Word64-                 in [f 0 ~?= 0, f 4294967295 ~?= 4294967295]-            , "TryFrom Word32 Word"-              ~: let f = hush . Witch.tryFrom @Word.Word32 @Word-                 in [f 0 ~?= Just 0, f 4294967295 ~?= Just 4294967295]-            , "From Word32 Natural"-              ~: let f = Witch.from @Word.Word32 @Natural.Natural-                 in [f 0 ~?= 0, f 4294967295 ~?= 4294967295]-            , "TryFrom Word32 Int8"-              ~: let f = hush . Witch.tryFrom @Word.Word32 @Int.Int8-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f 128 ~?= Nothing]-            , "TryFrom Word32 Int16"-              ~: let f = hush . Witch.tryFrom @Word.Word32 @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   ]-            , "TryFrom Word32 Int32"-              ~: let f = hush . Witch.tryFrom @Word.Word32 @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f 2147483648 ~?= Nothing-                   ]-            , "From Word32 Int64"-              ~: let f = Witch.from @Word.Word32 @Int.Int64-                 in [f 0 ~?= 0, f 4294967295 ~?= 4294967295]-            , "TryFrom Word32 Int"-              ~: let f = hush . Witch.tryFrom @Word.Word32 @Int-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int-                     in-                       if toInteger x >= 4294967295-                         then f 4294967295 ~?= Just 4294967295-                         else f (fromIntegral x) ~?= Just x-                   ]-            , "From Word32 Integer"-              ~: let f = Witch.from @Word.Word32 @Integer-                 in [f 0 ~?= 0, f 4294967295 ~?= 4294967295]-            , "TryFrom Word32 Float"-              ~: let f = hush . Witch.tryFrom @Word.Word32 @Float-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   ]-            , "From Word32 Double"-              ~: let f = Witch.from @Word.Word32 @Double-                 in [f 0 ~?= 0, f 4294967295 ~?= 4294967295]--    -- Word64-            , "TryFrom Word64 Word8"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Word.Word8-                 in [f 0 ~?= Just 0, f 255 ~?= Just 255, f 256 ~?= Nothing]-            , "TryFrom Word64 Word16"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   ]-            , "TryFrom Word64 Word32"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , f 4294967295 ~?= Just 4294967295-                   , f 4294967296 ~?= Nothing-                   ]-            , "TryFrom Word64 Word"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Word-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Word-                     in-                       if toInteger x >= 18446744073709551615-                         then f 18446744073709551615-                           ~?= Just 18446744073709551615-                         else f (fromIntegral x) ~?= Just x-                   ]-            , "From Word64 Natural"-              ~: let f = Witch.from @Word.Word64 @Natural.Natural-                 in-                   [f 0 ~?= 0, f 18446744073709551615 ~?= 18446744073709551615]-            , "TryFrom Word64 Int8"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Int.Int8-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f 128 ~?= Nothing]-            , "TryFrom Word64 Int16"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   ]-            , "TryFrom Word64 Int32"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f 2147483648 ~?= Nothing-                   ]-            , "TryFrom Word64 Int64"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Int.Int64-                 in-                   [ f 0 ~?= Just 0-                   , f 9223372036854775807 ~?= Just 9223372036854775807-                   , f 9223372036854775808 ~?= Nothing-                   ]-            , "TryFrom Word64 Int"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Int-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int-                     in-                       hush (Witch.tryFrom @Word.Word64 @Int (fromIntegral x))-                         ~?= Just x-                   , let x = fromIntegral (maxBound :: Int) + 1 :: Word.Word64-                     in hush (Witch.tryFrom @Word.Word64 @Int x) ~?= Nothing-                   ]-            , "From Word64 Integer"-              ~: let f = Witch.from @Word.Word64 @Integer-                 in-                   [f 0 ~?= 0, f 18446744073709551615 ~?= 18446744073709551615]-            , "TryFrom Word64 Float"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Float-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   ]-            , "TryFrom Word64 Double"-              ~: let f = hush . Witch.tryFrom @Word.Word64 @Double-                 in-                   [ f 0 ~?= Just 0-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f 9007199254740992 ~?= Nothing-                   ]--    -- Word-            , "TryFrom Word Word8"-              ~: let f = hush . Witch.tryFrom @Word @Word.Word8-                 in [f 0 ~?= Just 0, f 255 ~?= Just 255, f 256 ~?= Nothing]-            , "TryFrom Word Word16"-              ~: let f = hush . Witch.tryFrom @Word @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   ]-            , "TryFrom Word Word32"-              ~: let f = hush . Witch.tryFrom @Word @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , f 4294967295 ~?= Just 4294967295-                   , let x = maxBound :: Word-                     in-                       if toInteger x >= 4294967296-                         then f 4294967296 ~?= Nothing-                         else f x ~?= Just (fromIntegral x)-                   ]-            , "From Word Word64"-              ~: let f = Witch.from @Word @Word.Word64-                 in [f 0 ~?= 0, f maxBound ~?= fromIntegral (maxBound :: Word)]-            , "From Word Natural"-              ~: let f = Witch.from @Word @Natural.Natural-                 in [f 0 ~?= 0, f maxBound ~?= fromIntegral (maxBound :: Word)]-            , "TryFrom Word Int8"-              ~: let f = hush . Witch.tryFrom @Word @Int.Int8-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f 128 ~?= Nothing]-            , "TryFrom Word Int16"-              ~: let f = hush . Witch.tryFrom @Word @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   ]-            , "TryFrom Word Int32"-              ~: let f = hush . Witch.tryFrom @Word @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f 2147483648 ~?= Nothing-                   ]-            , "TryFrom Word Int64"-              ~: let f = hush . Witch.tryFrom @Word @Int.Int64-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Word-                     in-                       if toInteger x >= 9223372036854775807-                         then f 9223372036854775807-                           ~?= Just 9223372036854775807-                         else f x ~?= Just (fromIntegral x)-                   , let x = maxBound :: Word-                     in-                       if toInteger x >= 9223372036854775808-                         then f 9223372036854775808 ~?= Nothing-                         else f x ~?= Just (fromIntegral x)-                   ]-            , "TryFrom Word Int"-              ~: let f = hush . Witch.tryFrom @Word @Int-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int-                     in-                       hush (Witch.tryFrom @Word @Int (fromIntegral x))-                         ~?= Just x-                   , let x = fromIntegral (maxBound :: Int) + 1 :: Word-                     in hush (Witch.tryFrom @Word @Int x) ~?= Nothing-                   ]-            , "From Word Integer"-              ~: let f = Witch.from @Word @Integer-                 in [f 0 ~?= 0, f maxBound ~?= fromIntegral (maxBound :: Word)]-            , "TryFrom Word Float"-              ~: let f = hush . Witch.tryFrom @Word @Float-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   ]-            , "TryFrom Word Double"-              ~: let f = hush . Witch.tryFrom @Word @Double-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Word-                     in-                       if toInteger x >= 9007199254740991-                         then f 9007199254740991 ~?= Just 9007199254740991-                         else f x ~?= Just (fromIntegral x)-                   , let x = maxBound :: Word-                     in-                       if toInteger x >= 9007199254740992-                         then f 9007199254740992 ~?= Nothing-                         else f x ~?= Just (fromIntegral x)-                   ]--    -- Natural-            , "TryFrom Natural Word8"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Word.Word8-                 in [f 0 ~?= Just 0, f 255 ~?= Just 255, f 256 ~?= Nothing]-            , "TryFrom Natural Word16"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   ]-            , "TryFrom Natural Word32"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , f 4294967295 ~?= Just 4294967295-                   , f 4294967296 ~?= Nothing-                   ]-            , "TryFrom Natural Word64"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Word.Word64-                 in-                   [ f 0 ~?= Just 0-                   , f 18446744073709551615 ~?= Just 18446744073709551615-                   , f 18446744073709551616 ~?= Nothing-                   ]-            , "TryFrom Natural Word"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Word-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Word-                     in-                       hush-                           (Witch.tryFrom @Natural.Natural @Word-                             (fromIntegral x)-                           )-                         ~?= Just x-                   , let-                       x =-                         fromIntegral (maxBound :: Word) + 1 :: Natural.Natural-                     in-                       hush (Witch.tryFrom @Natural.Natural @Word x)-                         ~?= Nothing-                   ]-            , "TryFrom Natural Int8"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Int.Int8-                 in [f 0 ~?= Just 0, f 127 ~?= Just 127, f 128 ~?= Nothing]-            , "TryFrom Natural Int16"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   ]-            , "TryFrom Natural Int32"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f 2147483648 ~?= Nothing-                   ]-            , "TryFrom Natural Int64"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Int.Int64-                 in-                   [ f 0 ~?= Just 0-                   , f 9223372036854775807 ~?= Just 9223372036854775807-                   , f 9223372036854775808 ~?= Nothing-                   ]-            , "TryFrom Natural Int"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Int-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int-                     in-                       hush-                           (Witch.tryFrom @Natural.Natural @Int-                             (fromIntegral x)-                           )-                         ~?= Just x-                   , let-                       x =-                         fromIntegral (maxBound :: Int) + 1 :: Natural.Natural-                     in-                       hush (Witch.tryFrom @Natural.Natural @Int x) ~?= Nothing-                   ]-            , "From Natural Integer"-              ~: let f = Witch.from @Natural.Natural @Integer-                 in [f 0 ~?= 0, f 9223372036854775808 ~?= 9223372036854775808]-            , "TryFrom Natural Float"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Float-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   ]-            , "TryFrom Natural Double"-              ~: let f = hush . Witch.tryFrom @Natural.Natural @Double-                 in-                   [ f 0 ~?= Just 0-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f 9007199254740992 ~?= Nothing-                   ]--    -- Float-            , "TryFrom Float Int8"-              ~: let f = hush . Witch.tryFrom @Float @Int.Int8-                 in-                   [ f 0 ~?= Just 0-                   , f 127 ~?= Just 127-                   , f 128 ~?= Nothing-                   , f (-128) ~?= Just (-128)-                   , f (-129) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Int16"-              ~: let f = hush . Witch.tryFrom @Float @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   , f (-32768) ~?= Just (-32768)-                   , f (-32769) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Int32"-              ~: let f = hush . Witch.tryFrom @Float @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (-16777215) ~?= Just (-16777215)-                   , f (-16777216) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Int64"-              ~: let f = hush . Witch.tryFrom @Float @Int.Int64-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (-16777215) ~?= Just (-16777215)-                   , f (-16777216) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Int"-              ~: let f = hush . Witch.tryFrom @Float @Int-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (-16777215) ~?= Just (-16777215)-                   , f (-16777216) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Integer"-              ~: let f = hush . Witch.tryFrom @Float @Integer-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (-16777215) ~?= Just (-16777215)-                   , f (-16777216) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Word8"-              ~: let f = hush . Witch.tryFrom @Float @Word.Word8-                 in-                   [ f 0 ~?= Just 0-                   , f 255 ~?= Just 255-                   , f 256 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Word16"-              ~: let f = hush . Witch.tryFrom @Float @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Word32"-              ~: let f = hush . Witch.tryFrom @Float @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Word64"-              ~: let f = hush . Witch.tryFrom @Float @Word.Word64-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Word"-              ~: let f = hush . Witch.tryFrom @Float @Word-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Natural"-              ~: let f = hush . Witch.tryFrom @Float @Natural.Natural-                 in-                   [ f 0 ~?= Just 0-                   , f 16777215 ~?= Just 16777215-                   , f 16777216 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Float Rational"-              ~: let f = hush . Witch.tryFrom @Float @Rational-                 in-                   [ f 0 ~?= Just 0-                   , f (-0) ~?= Just 0-                   , f 0.5 ~?= Just 0.5-                   , f (-0.5) ~?= Just (-0.5)-                   , f 16777215 ~?= Just 16777215-                   , f (-16777215) ~?= Just (-16777215)-                   , f 16777216 ~?= Just 16777216-                   , f (-16777216) ~?= Just (-16777216)-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   , f 0.1 ~?= Just 0.1-                   , f (-0.1) ~?= Just (-0.1)-                   ]-            , "From Float Double"-              ~: let f = Witch.from @Float @Double-                 in-                   [ f 0 ~?= 0-                   , f 0.5 ~?= 0.5-                   , f (-0.5) ~?= (-0.5)-                   , TestCase-                     $ let x = f (0 / 0) in assertBool (show x) $ isNaN x-                   , f (1 / 0) ~?= (1 / 0)-                   , f (-1 / 0) ~?= (-1 / 0)-                   ]--    -- Double-            , "TryFrom Double Int8"-              ~: let f = hush . Witch.tryFrom @Double @Int.Int8-                 in-                   [ f 0 ~?= Just 0-                   , f 127 ~?= Just 127-                   , f 128 ~?= Nothing-                   , f (-128) ~?= Just (-128)-                   , f (-129) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Int16"-              ~: let f = hush . Witch.tryFrom @Double @Int.Int16-                 in-                   [ f 0 ~?= Just 0-                   , f 32767 ~?= Just 32767-                   , f 32768 ~?= Nothing-                   , f (-32768) ~?= Just (-32768)-                   , f (-32769) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Int32"-              ~: let f = hush . Witch.tryFrom @Double @Int.Int32-                 in-                   [ f 0 ~?= Just 0-                   , f 2147483647 ~?= Just 2147483647-                   , f 2147483648 ~?= Nothing-                   , f (-2147483648) ~?= Just (-2147483648)-                   , f (-2147483649) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Int64"-              ~: let f = hush . Witch.tryFrom @Double @Int.Int64-                 in-                   [ f 0 ~?= Just 0-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f 9007199254740992 ~?= Nothing-                   , f (-9007199254740991) ~?= Just (-9007199254740991)-                   , f (-9007199254740992) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Int"-              ~: let f = hush . Witch.tryFrom @Double @Int-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Int-                     in-                       if toInteger x >= 9007199254740991-                         then f 9007199254740991 ~?= Just 9007199254740991-                         else f (fromIntegral x) ~?= Just x-                   , f 9007199254740992 ~?= Nothing-                   , let x = minBound :: Int-                     in-                       if toInteger x <= (-9007199254740991)-                         then f (-9007199254740991)-                           ~?= Just (-9007199254740991)-                         else f (fromIntegral x) ~?= Just x-                   , f (-9007199254740992) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Integer"-              ~: let f = hush . Witch.tryFrom @Double @Integer-                 in-                   [ f 0 ~?= Just 0-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f 9007199254740992 ~?= Nothing-                   , f (-9007199254740991) ~?= Just (-9007199254740991)-                   , f (-9007199254740992) ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Word8"-              ~: let f = hush . Witch.tryFrom @Double @Word.Word8-                 in-                   [ f 0 ~?= Just 0-                   , f 255 ~?= Just 255-                   , f 256 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Word16"-              ~: let f = hush . Witch.tryFrom @Double @Word.Word16-                 in-                   [ f 0 ~?= Just 0-                   , f 65535 ~?= Just 65535-                   , f 65536 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Word32"-              ~: let f = hush . Witch.tryFrom @Double @Word.Word32-                 in-                   [ f 0 ~?= Just 0-                   , f 4294967295 ~?= Just 4294967295-                   , f 4294967296 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Word64"-              ~: let f = hush . Witch.tryFrom @Double @Word.Word64-                 in-                   [ f 0 ~?= Just 0-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f 9007199254740992 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Word"-              ~: let f = hush . Witch.tryFrom @Double @Word-                 in-                   [ f 0 ~?= Just 0-                   , let x = maxBound :: Word-                     in-                       if toInteger x >= 9007199254740991-                         then f 9007199254740991 ~?= Just 9007199254740991-                         else f (fromIntegral x) ~?= Just x-                   , f 9007199254740992 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Natural"-              ~: let f = hush . Witch.tryFrom @Double @Natural.Natural-                 in-                   [ f 0 ~?= Just 0-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f 9007199254740992 ~?= Nothing-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   ]-            , "TryFrom Double Rational"-              ~: let f = hush . Witch.tryFrom @Double @Rational-                 in-                   [ f 0 ~?= Just 0-                   , f (-0) ~?= Just 0-                   , f 0.5 ~?= Just 0.5-                   , f (-0.5) ~?= Just (-0.5)-                   , f 9007199254740991 ~?= Just 9007199254740991-                   , f (-9007199254740991) ~?= Just (-9007199254740991)-                   , f 9007199254740992 ~?= Just 9007199254740992-                   , f (-9007199254740992) ~?= Just (-9007199254740992)-                   , f (0 / 0) ~?= Nothing-                   , f (1 / 0) ~?= Nothing-                   , f (-1 / 0) ~?= Nothing-                   , f 0.1 ~?= Just 0.1-                   , f (-0.1) ~?= Just (-0.1)-                   ]-            , "From Double Float"-              ~: let f = Witch.from @Double @Float-                 in-                   [ f 0 ~?= 0-                   , f 0.5 ~?= 0.5-                   , f (-0.5) ~?= (-0.5)-                   , TestCase-                     $ let x = f (0 / 0) in assertBool (show x) $ isNaN x-                   , f (1 / 0) ~?= (1 / 0)-                   , f (-1 / 0) ~?= (-1 / 0)-                   ]--    -- Ratio-            , "From a (Ratio a)"-              ~: let f = Witch.from @Int @(Ratio.Ratio Int)-                 in [Witch.from @Integer @Rational 0 ~?= 0, f 0 ~?= 0]-            , "TryFrom (Ratio a) a"-              ~: let f = hush . Witch.tryFrom @(Ratio.Ratio Int) @Int-                 in-                   [ hush (Witch.tryFrom @Rational @Integer 0) ~?= Just 0-                   , hush (Witch.tryFrom @Rational @Integer 0.5) ~?= Nothing-                   , f 0 ~?= Just 0-                   , f 0.5 ~?= Nothing-                   ]-            , "From Rational Float"-              ~: let f = Witch.from @Rational @Float-                 in-                   [ f 0 ~?= 0-                   , f 0.5 ~?= 0.5-                   , f (-0.5) ~?= (-0.5)-                   , f 0.1 ~?= 0.1-                   , f (-0.1) ~?= (-0.1)-                   ]-            , "From Rational Double"-              ~: let f = Witch.from @Rational @Double-                 in-                   [ f 0 ~?= 0-                   , f 0.5 ~?= 0.5-                   , f (-0.5) ~?= (-0.5)-                   , f 0.1 ~?= 0.1-                   , f (-0.1) ~?= (-0.1)-                   ]-            , "TryFrom Rational (Fixed a)"-              ~: let f = hush . Witch.tryFrom @Rational @Fixed.Deci-                 in-                   [ hush (Witch.tryFrom @Rational @Fixed.Uni 1) ~?= Just 1-                   , hush (Witch.tryFrom @Rational @Fixed.Uni 1.2) ~?= Nothing-                   , f 0.1 ~?= Just 0.1-                   , f 1.2 ~?= Just 1.2-                   , f 12.3 ~?= Just 12.3-                   , f 0.12 ~?= Nothing-                   ]--    -- Fixed-            , "From Integer (Fixed a)"-              ~: let f = Witch.from @Integer @Fixed.Deci-                 in-                   [ Witch.from @Integer @Fixed.Uni 1 ~?= 1-                   , f 1 ~?= 0.1-                   , f 10 ~?= 1-                   , f 120 ~?= 12-                   ]-            , "From (Fixed a) Integer"-              ~: let f = Witch.from @Fixed.Deci @Integer-                 in-                   [ Witch.from @Fixed.Uni @Integer 1 ~?= 1-                   , f 0.1 ~?= 1-                   , f 1 ~?= 10-                   , f 12 ~?= 120-                   ]-            , "From (Fixed a) Rational"-              ~: let f = Witch.from @Fixed.Deci @Rational-                 in-                   [ Witch.from @Fixed.Uni @Rational 1 ~?= 1-                   , f 0.1 ~?= 0.1-                   , f 1 ~?= 1-                   , f 12 ~?= 12-                   ]--    -- Complex-            , "From a (Complex a)"-              ~: let f = Witch.from @Float @(Complex.Complex Float)-                 in-                   [ Witch.from @Double @(Complex.Complex Double) 1 ~?= 1-                   , f 1 ~?= 1-                   ]-            , "TryFrom (Complex a) a"-              ~: let f = hush . Witch.tryFrom @(Complex.Complex Float) @Float-                 in-                   [ hush (Witch.tryFrom @(Complex.Complex Double) @Double 1)-                     ~?= Just 1-                   , hush-                       (Witch.tryFrom @(Complex.Complex Double) @Double-                         (0 Complex.:+ 1)-                       )-                     ~?= Nothing-                   , f 1 ~?= Just 1-                   , f (0 Complex.:+ 1) ~?= Nothing-                   ]--    -- NonEmpty-            , "TryFrom [a] (NonEmpty a)"-              ~: let f = hush . Witch.tryFrom @[Int] @(NonEmpty.NonEmpty Int)-                 in-                   [ f [] ~?= Nothing-                   , f [1] ~?= Just (1 NonEmpty.:| [])-                   , f [1, 2] ~?= Just (1 NonEmpty.:| [2])-                   ]-            , "From (NonEmpty a) [a]"-              ~: let f = Witch.from @(NonEmpty.NonEmpty Int) @[Int]-                 in-                   [ f (1 NonEmpty.:| []) ~?= [1]-                   , f (1 NonEmpty.:| [2]) ~?= [1, 2]-                   ]--    -- Set-            , "From [a] (Set a)"-              ~: let f = Witch.from @[Char] @(Set.Set Char)-                 in-                   [ f [] ~?= Set.fromList []-                   , f ['a'] ~?= Set.fromList ['a']-                   , f ['a', 'b'] ~?= Set.fromList ['a', 'b']-                   , f ['a', 'a'] ~?= Set.fromList ['a']-                   ]-            , "From (Set a) [a]"-              ~: let f = Witch.from @(Set.Set Char) @[Char]-                 in-                   [ f (Set.fromList []) ~?= []-                   , f (Set.fromList ['a']) ~?= ['a']-                   , f (Set.fromList ['a', 'b']) ~?= ['a', 'b']-                   ]--    -- IntSet-            , "From [Int] IntSet"-              ~: let f = Witch.from @[Int] @IntSet.IntSet-                 in-                   [ f [] ~?= IntSet.fromList []-                   , f [1] ~?= IntSet.fromList [1]-                   , f [1, 2] ~?= IntSet.fromList [1, 2]-                   ]-            , "From IntSet [Int]"-              ~: let f = Witch.from @IntSet.IntSet @[Int]-                 in-                   [ f (IntSet.fromList []) ~?= []-                   , f (IntSet.fromList [1]) ~?= [1]-                   , f (IntSet.fromList [1, 2]) ~?= [1, 2]-                   ]--    -- Map-            , "From [(k, v)] (Map k v)"-              ~: let f = Witch.from @[(Char, Int)] @(Map.Map Char Int)-                 in-                   [ f [] ~?= Map.empty-                   , f [('a', 1)] ~?= Map.fromList [('a', 1)]-                   , f [('a', 1), ('b', 2)]-                     ~?= Map.fromList [('a', 1), ('b', 2)]-                   , f [('a', 1), ('a', 2)] ~?= Map.fromList [('a', 2)]-                   ]-            , "From (Map k v) [(k, v)]"-              ~: let f = Witch.from @(Map.Map Char Int) @[(Char, Int)]-                 in-                   [ f Map.empty ~?= []-                   , f (Map.fromList [('a', 1)]) ~?= [('a', 1)]-                   , f (Map.fromList [('a', 1), ('b', 2)])-                     ~?= [('a', 1), ('b', 2)]-                   ]--    -- IntMap-            , "From [(Int, v)] (IntMap v)"-              ~: let f = Witch.from @[(Int, Char)] @(IntMap.IntMap Char)-                 in-                   [ f [] ~?= IntMap.fromList []-                   , f [(1, 'a')] ~?= IntMap.fromList [(1, 'a')]-                   , f [(1, 'a'), (2, 'b')]-                     ~?= IntMap.fromList [(1, 'a'), (2, 'b')]-                   , f [(1, 'a'), (1, 'b')] ~?= IntMap.fromList [(1, 'b')]-                   ]-            , "From (IntMap v) [(Int, v)]"-              ~: let f = Witch.from @(IntMap.IntMap Char) @[(Int, Char)]-                 in-                   [ f (IntMap.fromList []) ~?= []-                   , f (IntMap.fromList [(1, 'a')]) ~?= [(1, 'a')]-                   , f (IntMap.fromList [(1, 'a'), (2, 'b')])-                     ~?= [(1, 'a'), (2, 'b')]-                   ]--    -- Seq-            , "From [a] (Seq a)"-              ~: let f = Witch.from @[Int] @(Seq.Seq Int)-                 in-                   [ f [] ~?= Seq.fromList []-                   , f [1] ~?= Seq.fromList [1]-                   , f [1, 2] ~?= Seq.fromList [1, 2]-                   ]-            , "From (Seq a) [a]"-              ~: let f = Witch.from @(Seq.Seq Int) @[Int]-                 in-                   [ f (Seq.fromList []) ~?= []-                   , f (Seq.fromList [1]) ~?= [1]-                   , f (Seq.fromList [1, 2]) ~?= [1, 2]-                   ]--    -- ByteString-            , "From [Word8] ByteString"-              ~: let f = Witch.from @[Word.Word8] @ByteString.ByteString-                 in-                   [ f [] ~?= ByteString.pack []-                   , f [0x00] ~?= ByteString.pack [0x00]-                   , f [0x0f, 0xf0] ~?= ByteString.pack [0x0f, 0xf0]-                   ]-            , "From ByteString [Word8]"-              ~: let f = Witch.from @ByteString.ByteString @[Word.Word8]-                 in-                   [ f (ByteString.pack []) ~?= []-                   , f (ByteString.pack [0x00]) ~?= [0x00]-                   , f (ByteString.pack [0x0f, 0xf0]) ~?= [0x0f, 0xf0]-                   ]-            , "From ByteString LazyByteString"-              ~: let-                   f =-                     Witch.from @ByteString.ByteString-                       @LazyByteString.ByteString-                 in-                   [ f (ByteString.pack []) ~?= LazyByteString.pack []-                   , f (ByteString.pack [0x00]) ~?= LazyByteString.pack [0x00]-                   , f (ByteString.pack [0x0f, 0xf0])-                     ~?= LazyByteString.pack [0x0f, 0xf0]-                   ]-            , "From ByteString ShortByteString"-              ~: let-                   f =-                     Witch.from @ByteString.ByteString-                       @ShortByteString.ShortByteString-                 in-                   [ f (ByteString.pack []) ~?= ShortByteString.pack []-                   , f (ByteString.pack [0x00]) ~?= ShortByteString.pack [0x00]-                   , f (ByteString.pack [0x0f, 0xf0])-                     ~?= ShortByteString.pack [0x0f, 0xf0]-                   ]-            , "TryFrom ByteString Text"-              ~: let-                   f = hush . Witch.tryFrom @ByteString.ByteString @Text.Text-                 in-                   [ f (ByteString.pack []) ~?= Just (Text.pack "")-                   , f (ByteString.pack [0x61]) ~?= Just (Text.pack "a")-                   , f (ByteString.pack [0xff]) ~?= Nothing-                   ]-            , "TryFrom ByteString LazyText"-              ~: let-                   f =-                     hush . Witch.tryFrom @ByteString.ByteString @LazyText.Text-                 in-                   [ f (ByteString.pack []) ~?= Just (LazyText.pack "")-                   , f (ByteString.pack [0x61]) ~?= Just (LazyText.pack "a")-                   , f (ByteString.pack [0xff]) ~?= Nothing-                   ]-            , "TryFrom ByteString String"-              ~: let f = hush . Witch.tryFrom @ByteString.ByteString @String-                 in-                   [ f (ByteString.pack []) ~?= Just ""-                   , f (ByteString.pack [0x61]) ~?= Just "a"-                   , f (ByteString.pack [0xff]) ~?= Nothing-                   ]--    -- LazyByteString-            , "From [Word8] LazyByteString"-              ~: let f = Witch.from @[Word.Word8] @LazyByteString.ByteString-                 in-                   [ f [] ~?= LazyByteString.pack []-                   , f [0x00] ~?= LazyByteString.pack [0x00]-                   , f [0x0f, 0xf0] ~?= LazyByteString.pack [0x0f, 0xf0]-                   ]-            , "From LazyByteString [Word8]"-              ~: let f = Witch.from @LazyByteString.ByteString @[Word.Word8]-                 in-                   [ f (LazyByteString.pack []) ~?= []-                   , f (LazyByteString.pack [0x00]) ~?= [0x00]-                   , f (LazyByteString.pack [0x0f, 0xf0]) ~?= [0x0f, 0xf0]-                   ]-            , "From LazyByteString ByteString"-              ~: let-                   f =-                     Witch.from @LazyByteString.ByteString-                       @ByteString.ByteString-                 in-                   [ f (LazyByteString.pack []) ~?= ByteString.pack []-                   , f (LazyByteString.pack [0x00]) ~?= ByteString.pack [0x00]-                   , f (LazyByteString.pack [0x0f, 0xf0])-                     ~?= ByteString.pack [0x0f, 0xf0]-                   ]-            , "TryFrom LazyByteString LazyText"-              ~: let-                   f =-                     hush-                       . Witch.tryFrom @LazyByteString.ByteString-                         @LazyText.Text-                 in-                   [ f (LazyByteString.pack []) ~?= Just (LazyText.pack "")-                   , f (LazyByteString.pack [0x61])-                     ~?= Just (LazyText.pack "a")-                   , f (LazyByteString.pack [0xff]) ~?= Nothing-                   ]-            , "TryFrom LazyByteString Text"-              ~: let-                   f =-                     hush . Witch.tryFrom @LazyByteString.ByteString @Text.Text-                 in-                   [ f (LazyByteString.pack []) ~?= Just (Text.pack "")-                   , f (LazyByteString.pack [0x61]) ~?= Just (Text.pack "a")-                   , f (LazyByteString.pack [0xff]) ~?= Nothing-                   ]-            , "TryFrom LazyByteString String"-              ~: let-                   f = hush . Witch.tryFrom @LazyByteString.ByteString @String-                 in-                   [ f (LazyByteString.pack []) ~?= Just ""-                   , f (LazyByteString.pack [0x61]) ~?= Just "a"-                   , f (LazyByteString.pack [0xff]) ~?= Nothing-                   ]--    -- ShortByteString-            , "From [Word8] ShortByteString"-              ~: let-                   f =-                     Witch.from @[Word.Word8] @ShortByteString.ShortByteString-                 in-                   [ f [] ~?= ShortByteString.pack []-                   , f [0x00] ~?= ShortByteString.pack [0x00]-                   , f [0x0f, 0xf0] ~?= ShortByteString.pack [0x0f, 0xf0]-                   ]-            , "From ShortByteString [Word8]"-              ~: let-                   f =-                     Witch.from @ShortByteString.ShortByteString @[Word.Word8]-                 in-                   [ f (ShortByteString.pack []) ~?= []-                   , f (ShortByteString.pack [0x00]) ~?= [0x00]-                   , f (ShortByteString.pack [0x0f, 0xf0]) ~?= [0x0f, 0xf0]-                   ]-            , "From ShortByteString ByteString"-              ~: let-                   f =-                     Witch.from @ShortByteString.ShortByteString-                       @ByteString.ByteString-                 in-                   [ f (ShortByteString.pack []) ~?= ByteString.pack []-                   , f (ShortByteString.pack [0x00]) ~?= ByteString.pack [0x00]-                   , f (ShortByteString.pack [0x0f, 0xf0])-                     ~?= ByteString.pack [0x0f, 0xf0]-                   ]--    -- Text-            , "From Text LazyText"-              ~: let f = Witch.from @Text.Text @LazyText.Text-                 in-                   [ f (Text.pack "") ~?= LazyText.pack ""-                   , f (Text.pack "a") ~?= LazyText.pack "a"-                   , f (Text.pack "ab") ~?= LazyText.pack "ab"-                   ]-            , "From Text ByteString"-              ~: let f = Witch.from @Text.Text @ByteString.ByteString-                 in-                   [ f (Text.pack "") ~?= ByteString.pack []-                   , f (Text.pack "a") ~?= ByteString.pack [0x61]-                   ]-            , "From Text LazyByteString"-              ~: let f = Witch.from @Text.Text @LazyByteString.ByteString-                 in-                   [ f (Text.pack "") ~?= LazyByteString.pack []-                   , f (Text.pack "a") ~?= LazyByteString.pack [0x61]-                   ]--    -- LazyText-            , "From LazyText Text"-              ~: let f = Witch.from @LazyText.Text @Text.Text-                 in-                   [ f (LazyText.pack "") ~?= Text.pack ""-                   , f (LazyText.pack "a") ~?= Text.pack "a"-                   , f (LazyText.pack "ab") ~?= Text.pack "ab"-                   ]-            , "From LazyText LazyByteString"-              ~: let f = Witch.from @LazyText.Text @LazyByteString.ByteString-                 in-                   [ f (LazyText.pack "") ~?= LazyByteString.pack []-                   , f (LazyText.pack "a") ~?= LazyByteString.pack [0x61]-                   ]-            , "From LazyText ByteString"-              ~: let f = Witch.from @LazyText.Text @ByteString.ByteString-                 in-                   [ f (LazyText.pack "") ~?= ByteString.pack []-                   , f (LazyText.pack "a") ~?= ByteString.pack [0x61]-                   ]--    -- String-            , "From String Text"-              ~: let f = Witch.from @String @Text.Text-                 in-                   [ f "" ~?= Text.pack ""-                   , f "a" ~?= Text.pack "a"-                   , f "ab" ~?= Text.pack "ab"-                   ]-            , "From Text String"-              ~: let f = Witch.from @Text.Text @String-                 in-                   [ f (Text.pack "") ~?= ""-                   , f (Text.pack "a") ~?= "a"-                   , f (Text.pack "ab") ~?= "ab"-                   ]-            , "From String LazyText"-              ~: let f = Witch.from @String @LazyText.Text-                 in-                   [ f "" ~?= LazyText.pack ""-                   , f "a" ~?= LazyText.pack "a"-                   , f "ab" ~?= LazyText.pack "ab"-                   ]-            , "From LazyText String"-              ~: let f = Witch.from @LazyText.Text @String-                 in-                   [ f (LazyText.pack "") ~?= ""-                   , f (LazyText.pack "a") ~?= "a"-                   , f (LazyText.pack "ab") ~?= "ab"-                   ]-            , "From String ByteString"-              ~: let f = Witch.from @String @ByteString.ByteString-                 in-                   [ f "" ~?= ByteString.pack []-                   , f "a" ~?= ByteString.pack [0x61]-                   ]-            , "From String LazyByteString"-              ~: let f = Witch.from @String @LazyByteString.ByteString-                 in-                   [ f "" ~?= LazyByteString.pack []-                   , f "a" ~?= LazyByteString.pack [0x61]-                   ]--    -- Day-            , "From Integer Day"-              ~: let f = Witch.from @Integer @Time.Day-                 in [f 0 ~?= Time.ModifiedJulianDay 0]-            , "From Day Integer"-              ~: let f = Witch.from @Time.Day @Integer-                 in [f (Time.ModifiedJulianDay 0) ~?= 0]--    -- DayOfWeek-            , "From Day DayOfWeek"-              ~: let f = Witch.from @Time.Day @Time.DayOfWeek-                 in [f (Time.ModifiedJulianDay 0) ~?= Time.Wednesday]--    -- UniversalTime-            , "From Rational UniversalTime"-              ~: let f = Witch.from @Rational @Time.UniversalTime-                 in [f 0 ~?= Time.ModJulianDate 0]-            , "From UniversalTime Rational"-              ~: let f = Witch.from @Time.UniversalTime @Rational-                 in [f (Time.ModJulianDate 0) ~?= 0]--    -- DiffTime-            , "From Pico DiffTime"-              ~: let f = Witch.from @Fixed.Pico @Time.DiffTime in [f 0 ~?= 0]-            , "From DiffTime Pico"-              ~: let f = Witch.from @Time.DiffTime @Fixed.Pico in [f 0 ~?= 0]--    -- NominalDiffTime-            , "From Pico NominalDiffTime"-              ~: let f = Witch.from @Fixed.Pico @Time.NominalDiffTime-                 in [f 0 ~?= 0]-            , "From NominalDiffTime Pico"-              ~: let f = Witch.from @Time.NominalDiffTime @Fixed.Pico-                 in [f 0 ~?= 0]--    -- POSIXTime-            , "From SystemTime POSIXTime"-              ~: let f = Witch.from @Time.SystemTime @Time.POSIXTime-                 in [f (Time.MkSystemTime 0 0) ~?= 0]-            , "From UTCTime POSIXTime"-              ~: let f = Witch.from @Time.UTCTime @Time.POSIXTime-                 in [f unixEpoch ~?= 0]-            , "From POSIXTime UTCTime"-              ~: let f = Witch.from @Time.POSIXTime @Time.UTCTime-                 in [f 0 ~?= unixEpoch]--    -- SystemTime-            , "From UTCTime SystemTime"-              ~: let f = Witch.from @Time.UTCTime @Time.SystemTime-                 in [f unixEpoch ~?= Time.MkSystemTime 0 0]-            , "From SystemTime AbsoluteTime"-              ~: let f = Witch.from @Time.SystemTime @Time.AbsoluteTime-                 in [f (Time.MkSystemTime (-3506716800) 0) ~?= Time.taiEpoch]-            , "From SystemTime UTCTime"-              ~: let f = Witch.from @Time.SystemTime @Time.UTCTime-                 in [f (Time.MkSystemTime 0 0) ~?= unixEpoch]--    -- TimeOfDay-            , "From DiffTime TimeOfDay"-              ~: let f = Witch.from @Time.DiffTime @Time.TimeOfDay-                 in [f 0 ~?= Time.TimeOfDay 0 0 0]-            , "From Rational TimeOfDay"-              ~: let f = Witch.from @Rational @Time.TimeOfDay-                 in [f 0 ~?= Time.TimeOfDay 0 0 0]-            , "From TimeOfDay DiffTime"-              ~: let f = Witch.from @Time.TimeOfDay @Time.DiffTime-                 in [f (Time.TimeOfDay 0 0 0) ~?= 0]-            , "From TimeOfDay Rational"-              ~: let f = Witch.from @Time.TimeOfDay @Rational-                 in [f (Time.TimeOfDay 0 0 0) ~?= 0]--    -- CalendarDiffTime-            , "From CalendarDiffDays CalendarDiffTime"-              ~: let-                   f =-                     Witch.from @Time.CalendarDiffDays @Time.CalendarDiffTime-                 in-                   [ f (Time.CalendarDiffDays 0 0)-                       ~?= Time.CalendarDiffTime 0 0-                   ]-            , "From NominalDiffTime CalendarDiffTime"-              ~: let-                   f = Witch.from @Time.NominalDiffTime @Time.CalendarDiffTime-                 in [f 0 ~?= Time.CalendarDiffTime 0 0]--    -- ZonedTime-            , "From ZonedTime UTCTime"-              ~: let f = Witch.from @Time.ZonedTime @Time.UTCTime-                 in-                   [ f-                         (Time.ZonedTime-                           (Time.LocalTime-                             (Time.ModifiedJulianDay 0)-                             (Time.TimeOfDay 0 0 0)-                           )-                           Time.utc-                         )-                       ~?= Time.UTCTime (Time.ModifiedJulianDay 0) 0-                   ]-            ]-       ]--unixEpoch :: Time.UTCTime-unixEpoch = Time.UTCTime (Time.ModifiedJulianDay 40587) 0--hush :: Either x a -> Maybe a-hush = either (const Nothing) Just--newtype Age-  = Age Int.Int8-  deriving (Eq, Show)--instance Witch.From Age Int.Int8--instance Witch.From Int.Int8 Age+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NegativeLiterals #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_GHC -Wno-error=overflowed-literals #-}++import qualified Control.Exception as Exception+import qualified Control.Monad.Trans.Writer as Writer+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Lazy as LazyByteString+import qualified Data.ByteString.Short as ShortByteString+import qualified Data.Complex as Complex+import qualified Data.Fixed as Fixed+import qualified Data.Foldable as Foldable+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.Time as Time+import qualified Data.Time.Clock.POSIX as Time+import qualified Data.Time.Clock.System as Time+import qualified Data.Time.Clock.TAI as Time+import qualified Data.Word as Word+import qualified GHC.Stack as Stack+import qualified Numeric.Natural as Natural+import qualified Test.HUnit as HUnit+import qualified Witch++main :: IO ()+main = HUnit.runTestTTAndExit $ specToTest spec++spec :: Spec+spec = describe "Witch" $ do+  describe "From" $ do+    describe "from" $ do+      it "works" $ do+        Witch.from @Int.Int8 @Int.Int16 1 `shouldBe` 1++  describe "TryFrom" $ do+    describe "tryFrom" $ do+      let f = hush . Witch.tryFrom @Int.Int16 @Int.Int8+      it "works" $ do+        f 1 `shouldBe` Just 1+        f 128 `shouldBe` Nothing++  describe "Utility" $ do+    describe "as" $ do+      it "works" $ do+        Witch.as @Int.Int8 1 `shouldBe` 1++    describe "into" $ do+      it "works" $ do+        Witch.into @Int.Int16 @Int.Int8 1 `shouldBe` 1++    describe "over" $ do+      it "works" $ do+        Witch.over @Int.Int8 (+ 1) (Age 1) `shouldBe` Age 2++    describe "via" $ do+      it "works" $ do+        Witch.via @Int.Int16 @Int.Int8 @Int.Int32 1 `shouldBe` 1++    describe "tryInto" $ do+      let f = hush . Witch.tryInto @Int.Int8 @Int.Int16+      it "works" $ do+        f 1 `shouldBe` Just 1+        f 128 `shouldBe` Nothing++    describe "tryVia" $ do+      let f = hush . Witch.tryVia @Int.Int16 @Int.Int32 @Int.Int8+      it "works" $ do+        f 1 `shouldBe` Just 1+        f 128 `shouldBe` Nothing+        f 32768 `shouldBe` Nothing++    describe "unsafeFrom" $ do+      let f = Witch.unsafeFrom @Int.Int16 @Int.Int8+      it "works" $ do+        f 1 `shouldBe` 1+        Exception.evaluate (f 128) `shouldThrow` anyTryFromException @Int.Int16 @Int.Int8++    describe "unsafeInto" $ do+      let f = Witch.unsafeInto @Int.Int8 @Int.Int16+      it "works" $ do+        f 1 `shouldBe` 1+        Exception.evaluate (f 128) `shouldThrow` anyTryFromException @Int.Int16 @Int.Int8++  describe "Lift" $ do+    describe "liftedFrom" $ do+      it "works" $ do+        $$(Witch.liftedFrom @Int.Int16 @Int.Int8 1) `shouldBe` 1++    describe "liftedInto" $ do+      it "works" $ do+        $$(Witch.liftedInto @Int.Int8 @Int.Int16 1) `shouldBe` 1++  describe "TryFromException" $ do+    describe "show" $ do+      it "works" $ do+        show (Witch.TryFromException @Int @Int 0 Nothing) `shouldBe` "TryFromException @Int @Int 0 Nothing"+        show+          ( Witch.TryFromException @(Seq.Seq Int) @(Seq.Seq Int)+              (Seq.fromList [])+              (Just (Exception.toException Exception.Overflow))+          )+          `shouldBe` "TryFromException @(Seq Int) @(Seq Int) (fromList []) (Just arithmetic overflow)"++  describe "Instances" $ do+    describe "From a a" $ do+      it "works" $ do+        Witch.from @Int @Int 0 `shouldBe` 0++    describe "From Int8 Int16" $ do+      let f = Witch.from @Int.Int8 @Int.Int16+      it "works" $ do+        f 0 `shouldBe` 0+        f 127 `shouldBe` 127+        f -128 `shouldBe` -128++    describe "From Int8 Int32" $ do+      let f = Witch.from @Int.Int8 @Int.Int32+      it "works" $ do+        f 0 `shouldBe` 0+        f 127 `shouldBe` 127+        f -128 `shouldBe` -128++    describe "From Int8 Int64" $ do+      let f = Witch.from @Int.Int8 @Int.Int64+      it "works" $ do+        f 0 `shouldBe` 0+        f 127 `shouldBe` 127+        f -128 `shouldBe` -128++    describe "From Int8 Int" $ do+      let f = Witch.from @Int.Int8 @Int+      it "works" $ do+        f 0 `shouldBe` 0+        f 127 `shouldBe` 127+        f -128 `shouldBe` -128++    describe "From Int8 Integer" $ do+      let f = Witch.from @Int.Int8 @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 127 `shouldBe` 127+        f -128 `shouldBe` -128++    describe "TryFrom Int8 Word8" $ do+      let f = hush . Witch.tryFrom @Int.Int8 @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f -1 `shouldBe` Nothing++    describe "TryFrom Int8 Word16" $ do+      let f = hush . Witch.tryFrom @Int.Int8 @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f -1 `shouldBe` Nothing++    describe "TryFrom Int8 Word32" $ do+      let f = hush . Witch.tryFrom @Int.Int8 @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f -1 `shouldBe` Nothing++    describe "TryFrom Int8 Word64" $ do+      let f = hush . Witch.tryFrom @Int.Int8 @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f -1 `shouldBe` Nothing++    describe "TryFrom Int8 Word" $ do+      let f = hush . Witch.tryFrom @Int.Int8 @Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f -1 `shouldBe` Nothing++    describe "TryFrom Int8 Natural" $ do+      let f = hush . Witch.tryFrom @Int.Int8 @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f -1 `shouldBe` Nothing++    describe "From Int8 Float" $ do+      let f = Witch.from @Int.Int8 @Float+      it "works" $ do+        f 0 `shouldBe` 0+        f 127 `shouldBe` 127+        f -128 `shouldBe` -128++    describe "From Int8 Double" $ do+      let f = Witch.from @Int.Int8 @Double+      it "works" $ do+        f 0 `shouldBe` 0+        f 127 `shouldBe` 127+        f -128 `shouldBe` -128++    describe "TryFrom Int16 Int8" $ do+      let f = hush . Witch.tryFrom @Int.Int16 @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing+        f -128 `shouldBe` Just -128+        f -129 `shouldBe` Nothing++    describe "From Int16 Int32" $ do+      let f = Witch.from @Int.Int16 @Int.Int32+      it "works" $ do+        f 0 `shouldBe` 0+        f 32767 `shouldBe` 32767+        f -32768 `shouldBe` -32768++    describe "From Int16 Int64" $ do+      let f = Witch.from @Int.Int16 @Int.Int64+      it "works" $ do+        f 0 `shouldBe` 0+        f 32767 `shouldBe` 32767+        f -32768 `shouldBe` -32768++    describe "From Int16 Int" $ do+      let f = Witch.from @Int.Int16 @Int+      it "works" $ do+        f 0 `shouldBe` 0+        f 32767 `shouldBe` 32767+        f -32768 `shouldBe` -32768++    describe "From Int16 Integer" $ do+      let f = Witch.from @Int.Int16 @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 32767 `shouldBe` 32767+        f -32768 `shouldBe` -32768++    describe "TryFrom Int16 Word8" $ do+      let f = hush . Witch.tryFrom @Int.Int16 @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Int16 Word16" $ do+      let f = hush . Witch.tryFrom @Int.Int16 @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f -1 `shouldBe` Nothing++    describe "TryFrom Int16 Word32" $ do+      let f = hush . Witch.tryFrom @Int.Int16 @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f -1 `shouldBe` Nothing++    describe "TryFrom Int16 Word64" $ do+      let f = hush . Witch.tryFrom @Int.Int16 @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f -1 `shouldBe` Nothing++    describe "TryFrom Int16 Word" $ do+      let f = hush . Witch.tryFrom @Int.Int16 @Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f -1 `shouldBe` Nothing++    describe "TryFrom Int16 Natural" $ do+      let f = hush . Witch.tryFrom @Int.Int16 @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f -1 `shouldBe` Nothing++    describe "From Int16 Float" $ do+      let f = Witch.from @Int.Int16 @Float+      it "works" $ do+        f 0 `shouldBe` 0+        f 32767 `shouldBe` 32767+        f -32768 `shouldBe` -32768++    describe "From Int16 Double" $ do+      let f = Witch.from @Int.Int16 @Double+      it "works" $ do+        f 0 `shouldBe` 0+        f 32767 `shouldBe` 32767+        f -32768 `shouldBe` -32768++    describe "TryFrom Int32 Int8" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing+        f -128 `shouldBe` Just -128+        f -129 `shouldBe` Nothing++    describe "TryFrom Int32 Int16" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing+        f -32768 `shouldBe` Just -32768+        f -32769 `shouldBe` Nothing++    describe "From Int32 Int64" $ do+      let f = Witch.from @Int.Int32 @Int.Int64+      it "works" $ do+        f 0 `shouldBe` 0+        f 2147483647 `shouldBe` 2147483647+        f -2147483648 `shouldBe` -2147483648++    describe "TryFrom Int32 Int" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f -2147483648 `shouldBe` Just -2147483648++    describe "From Int32 Integer" $ do+      let f = Witch.from @Int.Int32 @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 2147483647 `shouldBe` 2147483647+        f -2147483648 `shouldBe` -2147483648++    describe "TryFrom Int32 Word8" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Int32 Word16" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Int32 Word32" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f -1 `shouldBe` Nothing++    describe "TryFrom Int32 Word64" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f -1 `shouldBe` Nothing++    describe "TryFrom Int32 Word" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f -1 `shouldBe` Nothing++    describe "TryFrom Int32 Natural" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f -1 `shouldBe` Nothing++    describe "TryFrom Int32 Float" $ do+      let f = hush . Witch.tryFrom @Int.Int32 @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f -16777215 `shouldBe` Just -16777215+        f -16777216 `shouldBe` Nothing++    describe "From Int32 Double" $ do+      let f = Witch.from @Int.Int32 @Double+      it "works" $ do+        f 0 `shouldBe` 0+        f 2147483647 `shouldBe` 2147483647+        f -2147483648 `shouldBe` -2147483648++    describe "TryFrom Int64 Int8" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing+        f -128 `shouldBe` Just -128+        f -129 `shouldBe` Nothing++    describe "TryFrom Int64 Int16" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing+        f -32768 `shouldBe` Just -32768+        f -32769 `shouldBe` Nothing++    describe "TryFrom Int64 Int32" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Int.Int32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f 2147483648 `shouldBe` Nothing+        f -2147483648 `shouldBe` Just -2147483648+        f -2147483649 `shouldBe` Nothing++    describe "TryFrom Int64 Int" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Int+          hi = maxBound :: Int+          lo = minBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 9223372036854775807+          then f 9223372036854775807 `shouldBe` Just 9223372036854775807+          else f (fromIntegral hi) `shouldBe` Just hi+        if toInteger lo <= -9223372036854775808+          then f -9223372036854775808 `shouldBe` Just -9223372036854775808+          else f (fromIntegral lo) `shouldBe` Just lo++    describe "From Int64 Integer" $ do+      let f = Witch.from @Int.Int64 @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 9223372036854775807 `shouldBe` 9223372036854775807+        f -9223372036854775808 `shouldBe` -9223372036854775808++    describe "TryFrom Int64 Word8" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Int64 Word16" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Int64 Word32" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f -1 `shouldBe` Nothing++    describe "TryFrom Int64 Word64" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9223372036854775807 `shouldBe` Just 9223372036854775807+        f -1 `shouldBe` Nothing++    describe "TryFrom Int64 Word" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Word+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 9223372036854775807+          then f 9223372036854775807 `shouldBe` Just 9223372036854775807+          else f (fromIntegral hi) `shouldBe` Just hi+        f -1 `shouldBe` Nothing++    describe "TryFrom Int64 Natural" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9223372036854775807 `shouldBe` Just 9223372036854775807+        f -1 `shouldBe` Nothing++    describe "TryFrom Int64 Float" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f -16777215 `shouldBe` Just -16777215+        f -16777216 `shouldBe` Nothing++    describe "TryFrom Int64 Double" $ do+      let f = hush . Witch.tryFrom @Int.Int64 @Double+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f 9007199254740992 `shouldBe` Nothing+        f -9007199254740991 `shouldBe` Just -9007199254740991+        f -9007199254740992 `shouldBe` Nothing++    describe "TryFrom Int Int8" $ do+      let f = hush . Witch.tryFrom @Int @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing+        f -128 `shouldBe` Just -128+        f -129 `shouldBe` Nothing++    describe "TryFrom Int Int16" $ do+      let f = hush . Witch.tryFrom @Int @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing+        f -32768 `shouldBe` Just -32768+        f -32769 `shouldBe` Nothing++    describe "TryFrom Int Int32" $ do+      let f = hush . Witch.tryFrom @Int @Int.Int32+          hi = maxBound :: Int+          lo = minBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        if toInteger hi >= 2147483648+          then f 2147483648 `shouldBe` Nothing+          else f hi `shouldBe` Just (fromIntegral hi)+        f -2147483648 `shouldBe` Just -2147483648+        if toInteger lo <= -2147483649+          then f -2147483649 `shouldBe` Nothing+          else f lo `shouldBe` Just (fromIntegral lo)++    describe "From Int Int64" $ do+      let f = Witch.from @Int @Int.Int64+      it "works" $ do+        f 0 `shouldBe` 0+        f maxBound `shouldBe` fromIntegral (maxBound :: Int)+        f minBound `shouldBe` fromIntegral (minBound :: Int)++    describe "From Int Integer" $ do+      let f = Witch.from @Int @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f maxBound `shouldBe` fromIntegral (maxBound :: Int)+        f minBound `shouldBe` fromIntegral (minBound :: Int)++    describe "TryFrom Int Word8" $ do+      let f = hush . Witch.tryFrom @Int @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Int Word16" $ do+      let f = hush . Witch.tryFrom @Int @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Int Word32" $ do+      let f = hush . Witch.tryFrom @Int @Word.Word32+          hi = maxBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 4294967295+          then f 4294967295 `shouldBe` Just 4294967295+          else f hi `shouldBe` Just (fromIntegral hi)+        if toInteger hi >= 4294967296+          then f 4294967296 `shouldBe` Nothing+          else f hi `shouldBe` Just (fromIntegral hi)+        f -1 `shouldBe` Nothing++    describe "TryFrom Int Word64" $ do+      let f = hush . Witch.tryFrom @Int @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f maxBound `shouldBe` Just (fromIntegral (maxBound :: Int))+        f -1 `shouldBe` Nothing++    describe "TryFrom Int Word" $ do+      let f = hush . Witch.tryFrom @Int @Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f maxBound `shouldBe` Just (fromIntegral (maxBound :: Int))+        f -1 `shouldBe` Nothing++    describe "TryFrom Int Natural" $ do+      let f = hush . Witch.tryFrom @Int @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` Just 0+        f maxBound `shouldBe` Just (fromIntegral (maxBound :: Int))+        f -1 `shouldBe` Nothing++    describe "TryFrom Int Float" $ do+      let f = hush . Witch.tryFrom @Int @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f -16777215 `shouldBe` Just -16777215+        f -16777216 `shouldBe` Nothing++    describe "TryFrom Int Double" $ do+      let f = hush . Witch.tryFrom @Int @Double+          hi = maxBound :: Int+          lo = minBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 9007199254740991+          then f 9007199254740991 `shouldBe` Just 9007199254740991+          else f hi `shouldBe` Just (fromIntegral hi)+        if toInteger hi >= 9007199254740992+          then f 9007199254740992 `shouldBe` Nothing+          else f hi `shouldBe` Just (fromIntegral hi)+        if toInteger lo <= -9007199254740991+          then f -9007199254740991 `shouldBe` Just -9007199254740991+          else f lo `shouldBe` Just (fromIntegral lo)+        if toInteger lo <= -9007199254740992+          then f -9007199254740992 `shouldBe` Nothing+          else f lo `shouldBe` Just (fromIntegral lo)++    describe "TryFrom Integer Int8" $ do+      let f = hush . Witch.tryFrom @Integer @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing+        f -128 `shouldBe` Just -128+        f -129 `shouldBe` Nothing++    describe "TryFrom Integer Int16" $ do+      let f = hush . Witch.tryFrom @Integer @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing+        f -32768 `shouldBe` Just -32768+        f -32769 `shouldBe` Nothing++    describe "TryFrom Integer Int32" $ do+      let f = hush . Witch.tryFrom @Integer @Int.Int32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f 2147483648 `shouldBe` Nothing+        f -2147483648 `shouldBe` Just -2147483648+        f -2147483649 `shouldBe` Nothing++    describe "TryFrom Integer Int64" $ do+      let f = hush . Witch.tryFrom @Integer @Int.Int64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9223372036854775807 `shouldBe` Just 9223372036854775807+        f 9223372036854775808 `shouldBe` Nothing+        f -9223372036854775808 `shouldBe` Just -9223372036854775808+        f -9223372036854775809 `shouldBe` Nothing++    describe "TryFrom Integer Int" $ do+      let f = hush . Witch.tryFrom @Integer @Int+          hi = maxBound :: Int+          lo = minBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        f (fromIntegral hi) `shouldBe` Just hi+        f (toInteger hi + 1) `shouldBe` Nothing+        f (fromIntegral lo) `shouldBe` Just lo+        f (toInteger lo - 1) `shouldBe` Nothing++    describe "TryFrom Integer Word8" $ do+      let f = hush . Witch.tryFrom @Integer @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Integer Word16" $ do+      let f = hush . Witch.tryFrom @Integer @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Integer Word32" $ do+      let f = hush . Witch.tryFrom @Integer @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 4294967295 `shouldBe` Just 4294967295+        f 4294967296 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Integer Word64" $ do+      let f = hush . Witch.tryFrom @Integer @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 18446744073709551615 `shouldBe` Just 18446744073709551615+        f 18446744073709551616 `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Integer Word" $ do+      let f = hush . Witch.tryFrom @Integer @Word+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f (fromIntegral hi) `shouldBe` Just hi+        f (toInteger hi + 1) `shouldBe` Nothing+        f -1 `shouldBe` Nothing++    describe "TryFrom Integer Natural" $ do+      let f = hush . Witch.tryFrom @Integer @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 18446744073709551616 `shouldBe` Just 18446744073709551616+        f -1 `shouldBe` Nothing++    describe "TryFrom Integer Float" $ do+      let f = hush . Witch.tryFrom @Integer @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f -16777215 `shouldBe` Just -16777215+        f -16777216 `shouldBe` Nothing++    describe "TryFrom Integer Double" $ do+      let f = hush . Witch.tryFrom @Integer @Double+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f 9007199254740992 `shouldBe` Nothing+        f -9007199254740991 `shouldBe` Just -9007199254740991+        f -9007199254740992 `shouldBe` Nothing++    describe "From Word8 Word16" $ do+      let f = Witch.from @Word.Word8 @Word.Word16+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Word32" $ do+      let f = Witch.from @Word.Word8 @Word.Word32+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Word64" $ do+      let f = Witch.from @Word.Word8 @Word.Word64+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Word" $ do+      let f = Witch.from @Word.Word8 @Word+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Natural" $ do+      let f = Witch.from @Word.Word8 @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "TryFrom Word8 Int8" $ do+      let f = hush . Witch.tryFrom @Word.Word8 @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing++    describe "From Word8 Int16" $ do+      let f = Witch.from @Word.Word8 @Int.Int16+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Int32" $ do+      let f = Witch.from @Word.Word8 @Int.Int32+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Int64" $ do+      let f = Witch.from @Word.Word8 @Int.Int64+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Int" $ do+      let f = Witch.from @Word.Word8 @Int+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Integer" $ do+      let f = Witch.from @Word.Word8 @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Float" $ do+      let f = Witch.from @Word.Word8 @Float+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "From Word8 Double" $ do+      let f = Witch.from @Word.Word8 @Double+      it "works" $ do+        f 0 `shouldBe` 0+        f 255 `shouldBe` 255++    describe "TryFrom Word16 Word8" $ do+      let f = hush . Witch.tryFrom @Word.Word16 @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing++    describe "From Word16 Word32" $ do+      let f = Witch.from @Word.Word16 @Word.Word32+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "From Word16 Word64" $ do+      let f = Witch.from @Word.Word16 @Word.Word64+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "From Word16 Word" $ do+      let f = Witch.from @Word.Word16 @Word+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "From Word16 Natural" $ do+      let f = Witch.from @Word.Word16 @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "TryFrom Word16 Int8" $ do+      let f = hush . Witch.tryFrom @Word.Word16 @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing++    describe "TryFrom Word16 Int16" $ do+      let f = hush . Witch.tryFrom @Word.Word16 @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing++    describe "From Word16 Int32" $ do+      let f = Witch.from @Word.Word16 @Int.Int32+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "From Word16 Int64" $ do+      let f = Witch.from @Word.Word16 @Int.Int64+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "From Word16 Int" $ do+      let f = Witch.from @Word.Word16 @Int+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "From Word16 Integer" $ do+      let f = Witch.from @Word.Word16 @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "From Word16 Float" $ do+      let f = Witch.from @Word.Word16 @Float+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "From Word16 Double" $ do+      let f = Witch.from @Word.Word16 @Double+      it "works" $ do+        f 0 `shouldBe` 0+        f 65535 `shouldBe` 65535++    describe "TryFrom Word32 Word8" $ do+      let f = hush . Witch.tryFrom @Word.Word32 @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing++    describe "TryFrom Word32 Word16" $ do+      let f = hush . Witch.tryFrom @Word.Word32 @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing++    describe "From Word32 Word64" $ do+      let f = Witch.from @Word.Word32 @Word.Word64+      it "works" $ do+        f 0 `shouldBe` 0+        f 4294967295 `shouldBe` 4294967295++    describe "TryFrom Word32 Word" $ do+      let f = hush . Witch.tryFrom @Word.Word32 @Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 4294967295 `shouldBe` Just 4294967295++    describe "From Word32 Natural" $ do+      let f = Witch.from @Word.Word32 @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` 0+        f 4294967295 `shouldBe` 4294967295++    describe "TryFrom Word32 Int8" $ do+      let f = hush . Witch.tryFrom @Word.Word32 @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing++    describe "TryFrom Word32 Int16" $ do+      let f = hush . Witch.tryFrom @Word.Word32 @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing++    describe "TryFrom Word32 Int32" $ do+      let f = hush . Witch.tryFrom @Word.Word32 @Int.Int32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f 2147483648 `shouldBe` Nothing++    describe "From Word32 Int64" $ do+      let f = Witch.from @Word.Word32 @Int.Int64+      it "works" $ do+        f 0 `shouldBe` 0+        f 4294967295 `shouldBe` 4294967295++    describe "TryFrom Word32 Int" $ do+      let f = hush . Witch.tryFrom @Word.Word32 @Int+          hi = maxBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 4294967295+          then f 4294967295 `shouldBe` Just 4294967295+          else f (fromIntegral hi) `shouldBe` Just hi++    describe "From Word32 Integer" $ do+      let f = Witch.from @Word.Word32 @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 4294967295 `shouldBe` 4294967295++    describe "TryFrom Word32 Float" $ do+      let f = hush . Witch.tryFrom @Word.Word32 @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing++    describe "From Word32 Double" $ do+      let f = Witch.from @Word.Word32 @Double+      it "works" $ do+        f 0 `shouldBe` 0+        f 4294967295 `shouldBe` 4294967295++    describe "TryFrom Word64 Word8" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing++    describe "TryFrom Word64 Word16" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing++    describe "TryFrom Word64 Word32" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 4294967295 `shouldBe` Just 4294967295+        f 4294967296 `shouldBe` Nothing++    describe "TryFrom Word64 Word" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Word+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 18446744073709551615+          then f 18446744073709551615 `shouldBe` Just 18446744073709551615+          else f (fromIntegral hi) `shouldBe` Just hi++    describe "From Word64 Natural" $ do+      let f = Witch.from @Word.Word64 @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` 0+        f 18446744073709551615 `shouldBe` 18446744073709551615++    describe "TryFrom Word64 Int8" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing++    describe "TryFrom Word64 Int16" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing++    describe "TryFrom Word64 Int32" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Int.Int32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f 2147483648 `shouldBe` Nothing++    describe "TryFrom Word64 Int64" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Int.Int64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9223372036854775807 `shouldBe` Just 9223372036854775807+        f 9223372036854775808 `shouldBe` Nothing++    describe "TryFrom Word64 Int" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Int+          hi = maxBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        f (fromIntegral hi) `shouldBe` Just hi+        f (fromIntegral hi + 1) `shouldBe` Nothing++    describe "From Word64 Integer" $ do+      let f = Witch.from @Word.Word64 @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 18446744073709551615 `shouldBe` 18446744073709551615++    describe "TryFrom Word64 Float" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing++    describe "TryFrom Word64 Double" $ do+      let f = hush . Witch.tryFrom @Word.Word64 @Double+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f 9007199254740992 `shouldBe` Nothing++    describe "TryFrom Word Word8" $ do+      let f = hush . Witch.tryFrom @Word @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing++    describe "TryFrom Word Word16" $ do+      let f = hush . Witch.tryFrom @Word @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing++    describe "TryFrom Word Word32" $ do+      let f = hush . Witch.tryFrom @Word @Word.Word32+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 4294967295 `shouldBe` Just 4294967295+        if toInteger hi >= 4294967296+          then f 4294967296 `shouldBe` Nothing+          else f hi `shouldBe` Just (fromIntegral hi)++    describe "From Word Word64" $ do+      let f = Witch.from @Word @Word.Word64+      it "works" $ do+        f 0 `shouldBe` 0+        f maxBound `shouldBe` fromIntegral (maxBound :: Word)++    describe "From Word Natural" $ do+      let f = Witch.from @Word @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` 0+        f maxBound `shouldBe` fromIntegral (maxBound :: Word)++    describe "TryFrom Word Int8" $ do+      let f = hush . Witch.tryFrom @Word @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing++    describe "TryFrom Word Int16" $ do+      let f = hush . Witch.tryFrom @Word @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing++    describe "TryFrom Word Int32" $ do+      let f = hush . Witch.tryFrom @Word @Int.Int32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f 2147483648 `shouldBe` Nothing++    describe "TryFrom Word Int64" $ do+      let f = hush . Witch.tryFrom @Word @Int.Int64+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 9223372036854775807+          then f 9223372036854775807 `shouldBe` Just 9223372036854775807+          else f hi `shouldBe` Just (fromIntegral hi)+        if toInteger hi >= 9223372036854775808+          then f 9223372036854775808 `shouldBe` Nothing+          else f hi `shouldBe` Just (fromIntegral hi)++    describe "TryFrom Word Int" $ do+      let f = hush . Witch.tryFrom @Word @Int+          hi = maxBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        f (fromIntegral hi) `shouldBe` Just hi+        f (fromIntegral hi + 1) `shouldBe` Nothing++    describe "From Word Integer" $ do+      let f = Witch.from @Word @Integer+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` 0+        f hi `shouldBe` fromIntegral hi++    describe "TryFrom Word Float" $ do+      let f = hush . Witch.tryFrom @Word @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing++    describe "TryFrom Word Double" $ do+      let f = hush . Witch.tryFrom @Word @Double+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 9007199254740991+          then f 9007199254740991 `shouldBe` Just 9007199254740991+          else f hi `shouldBe` Just (fromIntegral hi)+        if toInteger hi >= 9007199254740992+          then f 9007199254740992 `shouldBe` Nothing+          else f hi `shouldBe` Just (fromIntegral hi)++    describe "TryFrom Natural Word8" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing++    describe "TryFrom Natural Word16" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing++    describe "TryFrom Natural Word32" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 4294967295 `shouldBe` Just 4294967295+        f 4294967296 `shouldBe` Nothing++    describe "TryFrom Natural Word64" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 18446744073709551615 `shouldBe` Just 18446744073709551615+        f 18446744073709551616 `shouldBe` Nothing++    describe "TryFrom Natural Word" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Word+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f (fromIntegral hi) `shouldBe` Just hi+        f (fromIntegral hi + 1) `shouldBe` Nothing++    describe "TryFrom Natural Int8" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing++    describe "TryFrom Natural Int16" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing++    describe "TryFrom Natural Int32" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Int.Int32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f 2147483648 `shouldBe` Nothing++    describe "TryFrom Natural Int64" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Int.Int64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9223372036854775807 `shouldBe` Just 9223372036854775807+        f 9223372036854775808 `shouldBe` Nothing++    describe "TryFrom Natural Int" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Int+          hi = maxBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        f (fromIntegral hi) `shouldBe` Just hi+        f (fromIntegral hi + 1) `shouldBe` Nothing++    describe "From Natural Integer" $ do+      let f = Witch.from @Natural.Natural @Integer+      it "works" $ do+        f 0 `shouldBe` 0+        f 9223372036854775808 `shouldBe` 9223372036854775808++    describe "TryFrom Natural Float" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing++    describe "TryFrom Natural Double" $ do+      let f = hush . Witch.tryFrom @Natural.Natural @Double+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f 9007199254740992 `shouldBe` Nothing++    describe "TryFrom Float Int8" $ do+      let f = hush . Witch.tryFrom @Float @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing+        f -128 `shouldBe` Just -128+        f -129 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Int16" $ do+      let f = hush . Witch.tryFrom @Float @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing+        f -32768 `shouldBe` Just -32768+        f -32769 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Int32" $ do+      let f = hush . Witch.tryFrom @Float @Int.Int32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f -16777215 `shouldBe` Just -16777215+        f -16777216 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Int64" $ do+      let f = hush . Witch.tryFrom @Float @Int.Int64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f -16777215 `shouldBe` Just -16777215+        f -16777216 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Int" $ do+      let f = hush . Witch.tryFrom @Float @Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f -16777215 `shouldBe` Just -16777215+        f -16777216 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Integer" $ do+      let f = hush . Witch.tryFrom @Float @Integer+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f -16777215 `shouldBe` Just -16777215+        f -16777216 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Word8" $ do+      let f = hush . Witch.tryFrom @Float @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Word16" $ do+      let f = hush . Witch.tryFrom @Float @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Word32" $ do+      let f = hush . Witch.tryFrom @Float @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Word64" $ do+      let f = hush . Witch.tryFrom @Float @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Word" $ do+      let f = hush . Witch.tryFrom @Float @Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Natural" $ do+      let f = hush . Witch.tryFrom @Float @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 16777215 `shouldBe` Just 16777215+        f 16777216 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Float Rational" $ do+      let f = hush . Witch.tryFrom @Float @Rational+      it "works" $ do+        f 0 `shouldBe` Just 0+        f -0 `shouldBe` Just 0+        f 0.5 `shouldBe` Just 0.5+        f (-0.5) `shouldBe` Just (-0.5)+        f 16777215 `shouldBe` Just 16777215+        f -16777215 `shouldBe` Just -16777215+        f 16777216 `shouldBe` Just 16777216+        f -16777216 `shouldBe` Just -16777216+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing+        f 0.1 `shouldBe` Just 0.1+        f (-0.1) `shouldBe` Just (-0.1)++    describe "From Float Double" $ do+      let f = Witch.from @Float @Double+      it "works" $ do+        f 0 `shouldBe` 0+        f 0.5 `shouldBe` 0.5+        f (-0.5) `shouldBe` (-0.5)+        f (0 / 0) `shouldSatisfy` isNaN+        f (1 / 0) `shouldBe` (1 / 0)+        f (-1 / 0) `shouldBe` (-1 / 0)++    describe "TryFrom Double Int8" $ do+      let f = hush . Witch.tryFrom @Double @Int.Int8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 127 `shouldBe` Just 127+        f 128 `shouldBe` Nothing+        f -128 `shouldBe` Just -128+        f -129 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Int16" $ do+      let f = hush . Witch.tryFrom @Double @Int.Int16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 32767 `shouldBe` Just 32767+        f 32768 `shouldBe` Nothing+        f -32768 `shouldBe` Just -32768+        f -32769 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Int32" $ do+      let f = hush . Witch.tryFrom @Double @Int.Int32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 2147483647 `shouldBe` Just 2147483647+        f 2147483648 `shouldBe` Nothing+        f -2147483648 `shouldBe` Just -2147483648+        f -2147483649 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Int64" $ do+      let f = hush . Witch.tryFrom @Double @Int.Int64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f 9007199254740992 `shouldBe` Nothing+        f -9007199254740991 `shouldBe` Just -9007199254740991+        f -9007199254740992 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Int" $ do+      let f = hush . Witch.tryFrom @Double @Int+          hi = maxBound :: Int+          lo = minBound :: Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 9007199254740991+          then f 9007199254740991 `shouldBe` Just 9007199254740991+          else f (fromIntegral hi) `shouldBe` Just hi+        f 9007199254740992 `shouldBe` Nothing+        if toInteger lo <= -9007199254740991+          then f -9007199254740991 `shouldBe` Just -9007199254740991+          else f (fromIntegral lo) `shouldBe` Just lo+        f -9007199254740992 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Integer" $ do+      let f = hush . Witch.tryFrom @Double @Integer+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f 9007199254740992 `shouldBe` Nothing+        f -9007199254740991 `shouldBe` Just -9007199254740991+        f -9007199254740992 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Word8" $ do+      let f = hush . Witch.tryFrom @Double @Word.Word8+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 255 `shouldBe` Just 255+        f 256 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Word16" $ do+      let f = hush . Witch.tryFrom @Double @Word.Word16+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 65535 `shouldBe` Just 65535+        f 65536 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Word32" $ do+      let f = hush . Witch.tryFrom @Double @Word.Word32+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 4294967295 `shouldBe` Just 4294967295+        f 4294967296 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Word64" $ do+      let f = hush . Witch.tryFrom @Double @Word.Word64+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f 9007199254740992 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Word" $ do+      let f = hush . Witch.tryFrom @Double @Word+          hi = maxBound :: Word+      it "works" $ do+        f 0 `shouldBe` Just 0+        if toInteger hi >= 9007199254740991+          then f 9007199254740991 `shouldBe` Just 9007199254740991+          else f (fromIntegral hi) `shouldBe` Just hi+        f 9007199254740992 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Natural" $ do+      let f = hush . Witch.tryFrom @Double @Natural.Natural+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f 9007199254740992 `shouldBe` Nothing+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing++    describe "TryFrom Double Rational" $ do+      let f = hush . Witch.tryFrom @Double @Rational+      it "works" $ do+        f 0 `shouldBe` Just 0+        f -0 `shouldBe` Just 0+        f 0.5 `shouldBe` Just 0.5+        f (-0.5) `shouldBe` Just (-0.5)+        f 9007199254740991 `shouldBe` Just 9007199254740991+        f -9007199254740991 `shouldBe` Just -9007199254740991+        f 9007199254740992 `shouldBe` Just 9007199254740992+        f -9007199254740992 `shouldBe` Just -9007199254740992+        f (0 / 0) `shouldBe` Nothing+        f (1 / 0) `shouldBe` Nothing+        f (-1 / 0) `shouldBe` Nothing+        f 0.1 `shouldBe` Just 0.1+        f (-0.1) `shouldBe` Just (-0.1)++    describe "From Double Float" $ do+      let f = Witch.from @Double @Float+      it "works" $ do+        f 0 `shouldBe` 0+        f 0.5 `shouldBe` 0.5+        f (-0.5) `shouldBe` (-0.5)+        f (0 / 0) `shouldSatisfy` isNaN+        f (1 / 0) `shouldBe` (1 / 0)+        f (-1 / 0) `shouldBe` (-1 / 0)++    describe "From a (Ratio a)" $ do+      let f = Witch.from @Int @(Ratio.Ratio Int)+      it "works" $ do+        f 0 `shouldBe` 0+        f 1 `shouldBe` 1++    describe "TryFrom (Ratio a) a" $ do+      let f = hush . Witch.tryFrom @(Ratio.Ratio Int) @Int+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 0.5 `shouldBe` Nothing+        f 1 `shouldBe` Just 1++    describe "From Rational Float" $ do+      let f = Witch.from @Rational @Float+      it "works" $ do+        f 0 `shouldBe` 0+        f 0.5 `shouldBe` 0.5+        f (-0.5) `shouldBe` (-0.5)+        f 0.1 `shouldBe` 0.1+        f (-0.1) `shouldBe` (-0.1)++    describe "From Rational Double" $ do+      let f = Witch.from @Rational @Double+      it "works" $ do+        f 0 `shouldBe` 0+        f 0.5 `shouldBe` 0.5+        f (-0.5) `shouldBe` (-0.5)+        f 0.1 `shouldBe` 0.1+        f (-0.1) `shouldBe` (-0.1)++    describe "TryFrom Rational (Fixed a)" $ do+      let f = hush . Witch.tryFrom @Rational @Fixed.Deci+      it "works" $ do+        f 0.1 `shouldBe` Just 0.1+        f 1.2 `shouldBe` Just 1.2+        f 12.3 `shouldBe` Just 12.3+        f 0.12 `shouldBe` Nothing++    describe "From Integer (Fixed a)" $ do+      let f = Witch.from @Integer @Fixed.Deci+      it "works" $ do+        f 1 `shouldBe` 0.1+        f 10 `shouldBe` 1+        f 120 `shouldBe` 12++    describe "From (Fixed a) Integer" $ do+      let f = Witch.from @Fixed.Deci @Integer+      it "works" $ do+        f 0.1 `shouldBe` 1+        f 1 `shouldBe` 10+        f 12 `shouldBe` 120++    describe "From (Fixed a) Rational" $ do+      let f = Witch.from @Fixed.Deci @Rational+      it "works" $ do+        f 0.1 `shouldBe` 0.1+        f 1 `shouldBe` 1+        f 12 `shouldBe` 12++    describe "From a (Complex a)" $ do+      let f = Witch.from @Float @(Complex.Complex Float)+      it "works" $ do+        f 0 `shouldBe` 0+        f 1 `shouldBe` 1++    describe "TryFrom (Complex a) a" $ do+      let f = hush . Witch.tryFrom @(Complex.Complex Float) @Float+      it "works" $ do+        f 0 `shouldBe` Just 0+        f 1 `shouldBe` Just 1+        f (0 Complex.:+ 1) `shouldBe` Nothing++    describe "TryFrom [a] (NonEmpty a)" $ do+      let f = hush . Witch.tryFrom @[Int] @(NonEmpty.NonEmpty Int)+      it "works" $ do+        f [] `shouldBe` Nothing+        f [1] `shouldBe` Just (1 NonEmpty.:| [])+        f [1, 2] `shouldBe` Just (1 NonEmpty.:| [2])++    describe "From (NonEmpty a) [a]" $ do+      let f = Witch.from @(NonEmpty.NonEmpty Int) @[Int]+      it "works" $ do+        f (1 NonEmpty.:| []) `shouldBe` [1]+        f (1 NonEmpty.:| [2]) `shouldBe` [1, 2]++    describe "From [a] (Set a)" $ do+      let f = Witch.from @[Char] @(Set.Set Char)+      it "works" $ do+        f [] `shouldBe` Set.fromList []+        f ['a'] `shouldBe` Set.fromList ['a']+        f ['a', 'b'] `shouldBe` Set.fromList ['a', 'b']+        f ['a', 'a'] `shouldBe` Set.fromList ['a']++    describe "From (Set a) [a]" $ do+      let f = Witch.from @(Set.Set Char) @[Char]+      it "works" $ do+        f (Set.fromList []) `shouldBe` []+        f (Set.fromList ['a']) `shouldBe` ['a']+        f (Set.fromList ['a', 'b']) `shouldBe` ['a', 'b']++    describe "From [Int] IntSet" $ do+      let f = Witch.from @[Int] @IntSet.IntSet+      it "works" $ do+        f [] `shouldBe` IntSet.fromList []+        f [1] `shouldBe` IntSet.fromList [1]+        f [1, 2] `shouldBe` IntSet.fromList [1, 2]++    describe "From IntSet [Int]" $ do+      let f = Witch.from @IntSet.IntSet @[Int]+      it "works" $ do+        f (IntSet.fromList []) `shouldBe` []+        f (IntSet.fromList [1]) `shouldBe` [1]+        f (IntSet.fromList [1, 2]) `shouldBe` [1, 2]++    describe "From [(k, v)] (Map k v)" $ do+      let f = Witch.from @[(Char, Int)] @(Map.Map Char Int)+      it "works" $ do+        f [] `shouldBe` Map.empty+        f [('a', 1)] `shouldBe` Map.fromList [('a', 1)]+        f [('a', 1), ('b', 2)] `shouldBe` Map.fromList [('a', 1), ('b', 2)]+        f [('a', 1), ('a', 2)] `shouldBe` Map.fromList [('a', 2)]++    describe "From (Map k v) [(k, v)]" $ do+      let f = Witch.from @(Map.Map Char Int) @[(Char, Int)]+      it "works" $ do+        f Map.empty `shouldBe` []+        f (Map.fromList [('a', 1)]) `shouldBe` [('a', 1)]+        f (Map.fromList [('a', 1), ('b', 2)]) `shouldBe` [('a', 1), ('b', 2)]++    describe "From [(Int, v)] (IntMap v)" $ do+      let f = Witch.from @[(Int, Char)] @(IntMap.IntMap Char)+      it "works" $ do+        f [] `shouldBe` IntMap.fromList []+        f [(1, 'a')] `shouldBe` IntMap.fromList [(1, 'a')]+        f [(1, 'a'), (2, 'b')] `shouldBe` IntMap.fromList [(1, 'a'), (2, 'b')]+        f [(1, 'a'), (1, 'b')] `shouldBe` IntMap.fromList [(1, 'b')]++    describe "From (IntMap v) [(Int, v)]" $ do+      let f = Witch.from @(IntMap.IntMap Char) @[(Int, Char)]+      it "works" $ do+        f (IntMap.fromList []) `shouldBe` []+        f (IntMap.fromList [(1, 'a')]) `shouldBe` [(1, 'a')]+        f (IntMap.fromList [(1, 'a'), (2, 'b')]) `shouldBe` [(1, 'a'), (2, 'b')]++    describe "From [a] (Seq a)" $ do+      let f = Witch.from @[Int] @(Seq.Seq Int)+      it "works" $ do+        f [] `shouldBe` Seq.fromList []+        f [1] `shouldBe` Seq.fromList [1]+        f [1, 2] `shouldBe` Seq.fromList [1, 2]++    describe "From (Seq a) [a]" $ do+      let f = Witch.from @(Seq.Seq Int) @[Int]+      it "works" $ do+        f (Seq.fromList []) `shouldBe` []+        f (Seq.fromList [1]) `shouldBe` [1]+        f (Seq.fromList [1, 2]) `shouldBe` [1, 2]++    describe "From [Word8] ByteString" $ do+      let f = Witch.from @[Word.Word8] @ByteString.ByteString+      it "works" $ do+        f [] `shouldBe` ByteString.pack []+        f [0x00] `shouldBe` ByteString.pack [0x00]+        f [0x0f, 0xf0] `shouldBe` ByteString.pack [0x0f, 0xf0]++    describe "From ByteString [Word8]" $ do+      let f = Witch.from @ByteString.ByteString @[Word.Word8]+      it "works" $ do+        f (ByteString.pack []) `shouldBe` []+        f (ByteString.pack [0x00]) `shouldBe` [0x00]+        f (ByteString.pack [0x0f, 0xf0]) `shouldBe` [0x0f, 0xf0]++    describe "From ByteString LazyByteString" $ do+      let f = Witch.from @ByteString.ByteString @LazyByteString.ByteString+      it "works" $ do+        f (ByteString.pack []) `shouldBe` LazyByteString.pack []+        f (ByteString.pack [0x00]) `shouldBe` LazyByteString.pack [0x00]+        f (ByteString.pack [0x0f, 0xf0]) `shouldBe` LazyByteString.pack [0x0f, 0xf0]++    describe "From ByteString ShortByteString" $ do+      let f = Witch.from @ByteString.ByteString @ShortByteString.ShortByteString+      it "works" $ do+        f (ByteString.pack []) `shouldBe` ShortByteString.pack []+        f (ByteString.pack [0x00]) `shouldBe` ShortByteString.pack [0x00]+        f (ByteString.pack [0x0f, 0xf0]) `shouldBe` ShortByteString.pack [0x0f, 0xf0]++    describe "TryFrom ByteString Text" $ do+      let f = hush . Witch.tryFrom @ByteString.ByteString @Text.Text+      it "works" $ do+        f (ByteString.pack []) `shouldBe` Just (Text.pack "")+        f (ByteString.pack [0x61]) `shouldBe` Just (Text.pack "a")+        f (ByteString.pack [0xff]) `shouldBe` Nothing++    describe "TryFrom ByteString LazyText" $ do+      let f = hush . Witch.tryFrom @ByteString.ByteString @LazyText.Text+      it "works" $ do+        f (ByteString.pack []) `shouldBe` Just (LazyText.pack "")+        f (ByteString.pack [0x61]) `shouldBe` Just (LazyText.pack "a")+        f (ByteString.pack [0xff]) `shouldBe` Nothing++    describe "TryFrom ByteString String" $ do+      let f = hush . Witch.tryFrom @ByteString.ByteString @String+      it "works" $ do+        f (ByteString.pack []) `shouldBe` Just ""+        f (ByteString.pack [0x61]) `shouldBe` Just "a"+        f (ByteString.pack [0xff]) `shouldBe` Nothing++    describe "From [Word8] LazyByteString" $ do+      let f = Witch.from @[Word.Word8] @LazyByteString.ByteString+      it "works" $ do+        f [] `shouldBe` LazyByteString.pack []+        f [0x00] `shouldBe` LazyByteString.pack [0x00]+        f [0x0f, 0xf0] `shouldBe` LazyByteString.pack [0x0f, 0xf0]++    describe "From LazyByteString [Word8]" $ do+      let f = Witch.from @LazyByteString.ByteString @[Word.Word8]+      it "works" $ do+        f (LazyByteString.pack []) `shouldBe` []+        f (LazyByteString.pack [0x00]) `shouldBe` [0x00]+        f (LazyByteString.pack [0x0f, 0xf0]) `shouldBe` [0x0f, 0xf0]++    describe "From LazyByteString ByteString" $ do+      let f = Witch.from @LazyByteString.ByteString @ByteString.ByteString+      it "works" $ do+        f (LazyByteString.pack []) `shouldBe` ByteString.pack []+        f (LazyByteString.pack [0x00]) `shouldBe` ByteString.pack [0x00]+        f (LazyByteString.pack [0x0f, 0xf0]) `shouldBe` ByteString.pack [0x0f, 0xf0]++    describe "TryFrom LazyByteString LazyText" $ do+      let f = hush . Witch.tryFrom @LazyByteString.ByteString @LazyText.Text+      it "works" $ do+        f (LazyByteString.pack []) `shouldBe` Just (LazyText.pack "")+        f (LazyByteString.pack [0x61]) `shouldBe` Just (LazyText.pack "a")+        f (LazyByteString.pack [0xff]) `shouldBe` Nothing++    describe "TryFrom LazyByteString Text" $ do+      let f = hush . Witch.tryFrom @LazyByteString.ByteString @Text.Text+      it "works" $ do+        f (LazyByteString.pack []) `shouldBe` Just (Text.pack "")+        f (LazyByteString.pack [0x61]) `shouldBe` Just (Text.pack "a")+        f (LazyByteString.pack [0xff]) `shouldBe` Nothing++    describe "TryFrom LazyByteString String" $ do+      let f = hush . Witch.tryFrom @LazyByteString.ByteString @String+      it "works" $ do+        f (LazyByteString.pack []) `shouldBe` Just ""+        f (LazyByteString.pack [0x61]) `shouldBe` Just "a"+        f (LazyByteString.pack [0xff]) `shouldBe` Nothing++    describe "From [Word8] ShortByteString" $ do+      let f = Witch.from @[Word.Word8] @ShortByteString.ShortByteString+      it "works" $ do+        f [] `shouldBe` ShortByteString.pack []+        f [0x00] `shouldBe` ShortByteString.pack [0x00]+        f [0x0f, 0xf0] `shouldBe` ShortByteString.pack [0x0f, 0xf0]++    describe "From ShortByteString [Word8]" $ do+      let f = Witch.from @ShortByteString.ShortByteString @[Word.Word8]+      it "works" $ do+        f (ShortByteString.pack []) `shouldBe` []+        f (ShortByteString.pack [0x00]) `shouldBe` [0x00]+        f (ShortByteString.pack [0x0f, 0xf0]) `shouldBe` [0x0f, 0xf0]++    describe "From ShortByteString ByteString" $ do+      let f = Witch.from @ShortByteString.ShortByteString @ByteString.ByteString+      it "works" $ do+        f (ShortByteString.pack []) `shouldBe` ByteString.pack []+        f (ShortByteString.pack [0x00]) `shouldBe` ByteString.pack [0x00]+        f (ShortByteString.pack [0x0f, 0xf0]) `shouldBe` ByteString.pack [0x0f, 0xf0]++    describe "From Text LazyText" $ do+      let f = Witch.from @Text.Text @LazyText.Text+      it "works" $ do+        f (Text.pack "") `shouldBe` LazyText.pack ""+        f (Text.pack "a") `shouldBe` LazyText.pack "a"+        f (Text.pack "ab") `shouldBe` LazyText.pack "ab"++    describe "From Text ByteString" $ do+      let f = Witch.from @Text.Text @ByteString.ByteString+      it "works" $ do+        f (Text.pack "") `shouldBe` ByteString.pack []+        f (Text.pack "a") `shouldBe` ByteString.pack [0x61]++    describe "From Text LazyByteString" $ do+      let f = Witch.from @Text.Text @LazyByteString.ByteString+      it "works" $ do+        f (Text.pack "") `shouldBe` LazyByteString.pack []+        f (Text.pack "a") `shouldBe` LazyByteString.pack [0x61]++    describe "From LazyText Text" $ do+      let f = Witch.from @LazyText.Text @Text.Text+      it "works" $ do+        f (LazyText.pack "") `shouldBe` Text.pack ""+        f (LazyText.pack "a") `shouldBe` Text.pack "a"+        f (LazyText.pack "ab") `shouldBe` Text.pack "ab"++    describe "From LazyText LazyByteString" $ do+      let f = Witch.from @LazyText.Text @LazyByteString.ByteString+      it "works" $ do+        f (LazyText.pack "") `shouldBe` LazyByteString.pack []+        f (LazyText.pack "a") `shouldBe` LazyByteString.pack [0x61]++    describe "From LazyText ByteString" $ do+      let f = Witch.from @LazyText.Text @ByteString.ByteString+      it "works" $ do+        f (LazyText.pack "") `shouldBe` ByteString.pack []+        f (LazyText.pack "a") `shouldBe` ByteString.pack [0x61]++    describe "From String Text" $ do+      let f = Witch.from @String @Text.Text+      it "works" $ do+        f "" `shouldBe` Text.pack ""+        f "a" `shouldBe` Text.pack "a"+        f "ab" `shouldBe` Text.pack "ab"++    describe "From Text String" $ do+      let f = Witch.from @Text.Text @String+      it "works" $ do+        f (Text.pack "") `shouldBe` ""+        f (Text.pack "a") `shouldBe` "a"+        f (Text.pack "ab") `shouldBe` "ab"++    describe "From String LazyText" $ do+      let f = Witch.from @String @LazyText.Text+      it "works" $ do+        f "" `shouldBe` LazyText.pack ""+        f "a" `shouldBe` LazyText.pack "a"+        f "ab" `shouldBe` LazyText.pack "ab"++    describe "From LazyText String" $ do+      let f = Witch.from @LazyText.Text @String+      it "works" $ do+        f (LazyText.pack "") `shouldBe` ""+        f (LazyText.pack "a") `shouldBe` "a"+        f (LazyText.pack "ab") `shouldBe` "ab"++    describe "From String ByteString" $ do+      let f = Witch.from @String @ByteString.ByteString+      it "works" $ do+        f "" `shouldBe` ByteString.pack []+        f "a" `shouldBe` ByteString.pack [0x61]++    describe "From String LazyByteString" $ do+      let f = Witch.from @String @LazyByteString.ByteString+      it "works" $ do+        f "" `shouldBe` LazyByteString.pack []+        f "a" `shouldBe` LazyByteString.pack [0x61]++    describe "From Integer Day" $ do+      let f = Witch.from @Integer @Time.Day+      it "works" $ do+        f 0 `shouldBe` Time.ModifiedJulianDay 0++    describe "From Day Integer" $ do+      let f = Witch.from @Time.Day @Integer+      it "works" $ do+        f (Time.ModifiedJulianDay 0) `shouldBe` 0++    describe "From Day DayOfWeek" $ do+      let f = Witch.from @Time.Day @Time.DayOfWeek+      it "works" $ do+        f (Time.ModifiedJulianDay 0) `shouldBe` Time.Wednesday++    describe "From Rational UniversalTime" $ do+      let f = Witch.from @Rational @Time.UniversalTime+      it "works" $ do+        f 0 `shouldBe` Time.ModJulianDate 0++    describe "From UniversalTime Rational" $ do+      let f = Witch.from @Time.UniversalTime @Rational+      it "works" $ do+        f (Time.ModJulianDate 0) `shouldBe` 0++    describe "From Pico DiffTime" $ do+      let f = Witch.from @Fixed.Pico @Time.DiffTime+      it "works" $ do+        f 0 `shouldBe` 0++    describe "From DiffTime Pico" $ do+      let f = Witch.from @Time.DiffTime @Fixed.Pico+      it "works" $ do+        f 0 `shouldBe` 0++    describe "From Pico NominalDiffTime" $ do+      let f = Witch.from @Fixed.Pico @Time.NominalDiffTime+      it "works" $ do+        f 0 `shouldBe` 0++    describe "From NominalDiffTime Pico" $ do+      let f = Witch.from @Time.NominalDiffTime @Fixed.Pico+      it "works" $ do+        f 0 `shouldBe` 0++    describe "From SystemTime POSIXTime" $ do+      let f = Witch.from @Time.SystemTime @Time.POSIXTime+      it "works" $ do+        f (Time.MkSystemTime 0 0) `shouldBe` 0++    describe "From UTCTime POSIXTime" $ do+      let f = Witch.from @Time.UTCTime @Time.POSIXTime+      it "works" $ do+        f unixEpoch `shouldBe` 0++    describe "From POSIXTime UTCTime" $ do+      let f = Witch.from @Time.POSIXTime @Time.UTCTime+      it "works" $ do+        f 0 `shouldBe` unixEpoch++    describe "From UTCTime SystemTime" $ do+      let f = Witch.from @Time.UTCTime @Time.SystemTime+      it "works" $ do+        f unixEpoch `shouldBe` Time.MkSystemTime 0 0++    describe "From SystemTime AbsoluteTime" $ do+      let f = Witch.from @Time.SystemTime @Time.AbsoluteTime+      it "works" $ do+        f (Time.MkSystemTime -3506716800 0) `shouldBe` Time.taiEpoch++    describe "From SystemTime UTCTime" $ do+      let f = Witch.from @Time.SystemTime @Time.UTCTime+      it "works" $ do+        f (Time.MkSystemTime 0 0) `shouldBe` unixEpoch++    describe "From DiffTime TimeOfDay" $ do+      let f = Witch.from @Time.DiffTime @Time.TimeOfDay+      it "works" $ do+        f 0 `shouldBe` Time.TimeOfDay 0 0 0++    describe "From Rational TimeOfDay" $ do+      let f = Witch.from @Rational @Time.TimeOfDay+      it "works" $ do+        f 0 `shouldBe` Time.TimeOfDay 0 0 0++    describe "From TimeOfDay DiffTime" $ do+      let f = Witch.from @Time.TimeOfDay @Time.DiffTime+      it "works" $ do+        f (Time.TimeOfDay 0 0 0) `shouldBe` 0++    describe "From TimeOfDay Rational" $ do+      let f = Witch.from @Time.TimeOfDay @Rational+      it "works" $ do+        f (Time.TimeOfDay 0 0 0) `shouldBe` 0++    describe "From CalendarDiffDays CalendarDiffTime" $ do+      let f = Witch.from @Time.CalendarDiffDays @Time.CalendarDiffTime+      it "works" $ do+        f (Time.CalendarDiffDays 0 0) `shouldBe` Time.CalendarDiffTime 0 0++    describe "From NominalDiffTime CalendarDiffTime" $ do+      let f = Witch.from @Time.NominalDiffTime @Time.CalendarDiffTime+      it "works" $ do+        f 0 `shouldBe` Time.CalendarDiffTime 0 0++    describe "From ZonedTime UTCTime" $ do+      let f = Witch.from @Time.ZonedTime @Time.UTCTime+      it "works" $ do+        f (Time.ZonedTime (Time.LocalTime (Time.ModifiedJulianDay 0) (Time.TimeOfDay 0 0 0)) Time.utc) `shouldBe` Time.UTCTime (Time.ModifiedJulianDay 0) 0++newtype Age+  = Age Int.Int8+  deriving (Eq, Show)++instance Witch.From Age Int.Int8++instance Witch.From Int.Int8 Age++type Selector e = e -> Bool++type Spec = Writer.Writer (Seq.Seq HUnit.Test) ()++anyTryFromException :: Selector (Witch.TryFromException s t)+anyTryFromException = const True++describe :: Stack.HasCallStack => String -> Spec -> Spec+describe label = testToSpec . HUnit.TestLabel label . specToTest++hush :: Either x a -> Maybe a+hush = either (const Nothing) Just++it :: Stack.HasCallStack => String -> HUnit.Assertion -> Spec+it label = testToSpec . HUnit.TestLabel label . HUnit.TestCase++shouldBe :: (Stack.HasCallStack, Eq a, Show a) => a -> a -> HUnit.Assertion+shouldBe = (HUnit.@?=)++shouldSatisfy :: (Stack.HasCallStack, Show a) => a -> (a -> Bool) -> HUnit.Assertion+shouldSatisfy value predicate = HUnit.assertBool ("predicate failed on: " ++ show value) $ predicate value++shouldThrow :: (Stack.HasCallStack, Exception.Exception e) => IO a -> Selector e -> HUnit.Assertion+shouldThrow action predicate = do+  result <- Exception.try action+  case result of+    Right _ -> HUnit.assertFailure "did not get expected exception"+    Left exception -> HUnit.assertBool ("predicate failed on expected exception: " ++ show exception) $ predicate exception++specToTest :: Stack.HasCallStack => Spec -> HUnit.Test+specToTest = HUnit.TestList . Foldable.toList . Writer.execWriter++testToSpec :: Stack.HasCallStack => HUnit.Test -> Spec+testToSpec = Writer.tell . Seq.singleton++unixEpoch :: Time.UTCTime+unixEpoch = Time.UTCTime (Time.fromGregorian 1970 1 1) 0
witch.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2  name: witch-version: 1.0.0.3+version: 1.0.0.4 synopsis: Convert values from one type into another. description: Witch converts values from one type into another. @@ -23,10 +23,9 @@  common library   build-depends:-    , base >= 4.10.0 && < 4.18+    , base >= 4.10 && < 4.18     , bytestring >= 0.10.8 && < 0.12     , containers >= 0.5.10 && < 0.7-    , template-haskell >= 2.12.0 && < 2.20     , text >= 1.2.3 && < 1.3 || >= 2.0 && < 2.1     , time >= 1.9.1 && < 1.13   default-language: Haskell2010@@ -69,13 +68,11 @@     -rtsopts     -threaded -  if impl(ghc >= 8.10)-    ghc-options:-      -Wno-unused-packages- library   import: library +  build-depends:+    , template-haskell >= 2.12 && < 2.20   exposed-modules:     Witch     Witch.From@@ -93,11 +90,12 @@   else     hs-source-dirs: source/ghc-8.8 -test-suite test+test-suite witch-test-suite   import: executable    build-depends:     , HUnit >= 1.6.1 && < 1.7+    , transformers >= 0.5.2 && < 0.7   hs-source-dirs: source/test-suite   main-is: Main.hs   type: exitcode-stdio-1.0