witch 0.3.4.2 → 1.0.0.1
raw patch · 23 files changed
+4024/−3947 lines, 23 filesdep ~HUnitPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: HUnit
API changes (from Hackage documentation)
- Witch.Instances: instance Witch.From.From (Witch.TryFromException.TryFromException s u) (Witch.TryFromException.TryFromException s t)
+ Witch.Instances: instance Witch.From.From (Witch.TryFromException.TryFromException source oldTarget) (Witch.TryFromException.TryFromException source newTarget)
+ Witch.Utility: withSource :: newSource -> TryFromException oldSource target -> TryFromException newSource target
+ Witch.Utility: withTarget :: forall newTarget source oldTarget. TryFromException source oldTarget -> TryFromException source newTarget
Files
- LICENSE.markdown +21/−0
- LICENSE.txt +0/−13
- source/ghc-8.10/Witch/Lift.hs +48/−0
- source/ghc-8.8/Witch/Lift.hs +48/−0
- source/ghc-9.0/Witch/Lift.hs +50/−0
- source/library/Witch.hs +258/−0
- source/library/Witch/From.hs +36/−0
- source/library/Witch/Instances.hs +1293/−0
- source/library/Witch/TryFrom.hs +26/−0
- source/library/Witch/TryFromException.hs +38/−0
- source/library/Witch/Utility.hs +199/−0
- source/test-suite/Main.hs +1981/−0
- src/ghc-8.10/Witch/Lift.hs +0/−48
- src/ghc-8.8/Witch/Lift.hs +0/−48
- src/ghc-9.0/Witch/Lift.hs +0/−50
- src/lib/Witch.hs +0/−258
- src/lib/Witch/From.hs +0/−36
- src/lib/Witch/Instances.hs +0/−1291
- src/lib/Witch/TryFrom.hs +0/−26
- src/lib/Witch/TryFromException.hs +0/−38
- src/lib/Witch/Utility.hs +0/−187
- src/test/Main.hs +0/−1931
- witch.cabal +26/−21
+ LICENSE.markdown view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2022 Taylor Fausak++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
− LICENSE.txt
@@ -1,13 +0,0 @@-Copyright 2021 Taylor Fausak--Permission to use, copy, modify, and/or distribute this software for any-purpose with or without fee is hereby granted, provided that the above-copyright notice and this permission notice appear in all copies.--THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND-FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR-PERFORMANCE OF THIS SOFTWARE.
+ source/ghc-8.10/Witch/Lift.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE ExplicitForAll #-}++module Witch.Lift where++import qualified Data.Typeable as Typeable+import qualified Language.Haskell.TH.Syntax as TH+import qualified Witch.TryFrom as TryFrom+import qualified Witch.Utility as Utility++-- | This is like 'Utility.unsafeFrom' except that it works at compile time+-- rather than runtime.+--+-- > -- Avoid this:+-- > unsafeFrom @s "some literal"+-- >+-- > -- 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 = TH.liftTyped . Utility.unsafeFrom++-- | This is like 'Utility.unsafeInto' except that it works at compile time+-- rather than runtime.+--+-- > -- Avoid this:+-- > unsafeInto @t "some literal"+-- >+-- > -- 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 = liftedFrom
+ source/ghc-8.8/Witch/Lift.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Witch.Lift where++import qualified Data.Typeable as Typeable+import qualified Language.Haskell.TH.Syntax as TH+import qualified Witch.TryFrom as TryFrom+import qualified Witch.Utility as Utility++-- | This is like 'Utility.unsafeFrom' except that it works at compile time+-- rather than runtime.+--+-- > -- Avoid this:+-- > unsafeFrom @s "some literal"+-- >+-- > -- 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 s = TH.unsafeTExpCoerce $ TH.lift (Utility.unsafeFrom s :: target)++-- | This is like 'Utility.unsafeInto' except that it works at compile time+-- rather than runtime.+--+-- > -- Avoid this:+-- > unsafeInto @t "some literal"+-- >+-- > -- 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 = liftedFrom
+ source/ghc-9.0/Witch/Lift.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE ExplicitForAll #-}++module Witch.Lift where++import qualified Data.Typeable as Typeable+import qualified Language.Haskell.TH.Syntax as TH+import qualified Witch.TryFrom as TryFrom+import qualified Witch.Utility as Utility++-- | This is like 'Utility.unsafeFrom' except that it works at compile time+-- rather than runtime.+--+-- > -- Avoid this:+-- > unsafeFrom @s "some literal"+-- >+-- > -- 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 = TH.liftTyped . Utility.unsafeFrom++-- | This is like 'Utility.unsafeInto' except that it works at compile time+-- rather than runtime.+--+-- > -- Avoid this:+-- > unsafeInto @t "some literal"+-- >+-- > -- 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 = liftedFrom
+ source/library/Witch.hs view
@@ -0,0 +1,258 @@+-- | The Witch package is a library that allows you to confidently convert+-- values between various types. This module exports everything you need to+-- perform conversions or define your own. It is designed to be imported+-- unqualified, so getting started is as easy as:+--+-- >>> import Witch+--+-- In typical usage, the functions that you will use most often are+-- 'Witch.Utility.into' for conversions that always succeed and+-- 'Witch.Utility.tryInto' for conversions that sometimes fail.+module Witch+ ( -- * Type classes++ -- ** From+ Witch.From.From(from)+ , Witch.Utility.into++ -- ** TryFrom+ , Witch.TryFrom.TryFrom(tryFrom)+ , Witch.Utility.tryInto++ -- * Data types+ , Witch.TryFromException.TryFromException(..)++ -- * 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++ -- ** 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++ -- * Notes++ -- ** 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.++ -- ** 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++ -- ** 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 ()+import qualified Witch.Lift+import qualified Witch.TryFrom+import qualified Witch.TryFromException+import qualified Witch.Utility
+ source/library/Witch/From.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}++module Witch.From where++import qualified Data.Coerce as Coerce++-- | This type class is for converting values from some @source@ type into+-- some other @target@ type. The constraint @'From' source target@ means that+-- you can convert from a value of type @source@ into a value of type+-- @target@.+--+-- This type class is for conversions that always succeed. If your conversion+-- sometimes fails, consider implementing @TryFrom@ instead.+class From source target where+ -- | This method implements the conversion of a value between types. At call+ -- sites you may prefer to use @into@ instead.+ --+ -- > -- Avoid this:+ -- > from (x :: s)+ -- >+ -- > -- Prefer this:+ -- > from @s x+ --+ -- The default implementation of this method simply calls 'Coerce.coerce',+ -- which works for types that have the same runtime representation. This+ -- means that for @newtype@s you do not need to implement this method at+ -- all. For example:+ --+ -- >>> newtype Name = Name String+ -- >>> 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
@@ -0,0 +1,1293 @@+{-# OPTIONS_GHC -Wno-orphans #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++module Witch.Instances where++import qualified Control.Exception as Exception+import qualified Data.Bits as Bits+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Lazy as LazyByteString+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 as List+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.Encoding as Text+import qualified Data.Text.Lazy as LazyText+import qualified Data.Text.Lazy.Encoding 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.Float as Float+import qualified Numeric+import qualified Numeric.Natural as Natural+import qualified Witch.From as From+import qualified Witch.TryFrom as TryFrom+import qualified Witch.TryFromException as TryFromException+import qualified Witch.Utility as Utility++-- | Uses 'id'.+instance From.From a a where+ from = id++-- Int8++-- | Uses 'fromIntegral'.+instance From.From Int.Int8 Int.Int16 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int8 Int.Int32 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int8 Int.Int64 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int8 Int where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int8 Integer where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int8 Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int8 Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int8 Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int8 Word.Word64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int8 Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral' when the input is not negative.+instance TryFrom.TryFrom Int.Int8 Natural.Natural where+ tryFrom = Utility.eitherTryFrom fromNonNegativeIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int8 Float where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int8 Double where+ from = fromIntegral++-- Int16++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int16 Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Int.Int16 Int.Int32 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int16 Int.Int64 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int16 Int where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int16 Integer where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int16 Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int16 Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int16 Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int16 Word.Word64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int16 Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral' when the input is not negative.+instance TryFrom.TryFrom Int.Int16 Natural.Natural where+ tryFrom = Utility.eitherTryFrom fromNonNegativeIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int16 Float where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int.Int16 Double where+ from = fromIntegral++-- Int32++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int32 Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int32 Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Int.Int32 Int.Int64 where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int32 Int where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Int.Int32 Integer where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int32 Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int32 Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int32 Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int32 Word.Word64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int32 Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral' when the input is not negative.+instance TryFrom.TryFrom Int.Int32 Natural.Natural where+ tryFrom = Utility.eitherTryFrom fromNonNegativeIntegral++-- | 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++-- | Uses 'fromIntegral'.+instance From.From Int.Int32 Double where+ from = fromIntegral++-- Int64++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Int.Int32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Int where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Int.Int64 Integer where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Word.Word64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int.Int64 Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral' when the input is not negative.+instance TryFrom.TryFrom Int.Int64 Natural.Natural where+ -- This should use @eitherTryFrom fromNonNegativeIntegral@, but that causes+ -- a bug in GHC 9.0.1.+ -- https://mail.haskell.org/pipermail/haskell-cafe/2021-March/133540.html+ tryFrom =+ Utility.eitherTryFrom $ \s -> TryFrom.tryFrom (From.from s :: Integer)++-- | 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++-- | 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++-- Int++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int Int.Int32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Int Int.Int64 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Int Integer where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int Word.Word64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Int Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral' when the input is not negative.+instance TryFrom.TryFrom Int Natural.Natural where+ tryFrom = Utility.eitherTryFrom fromNonNegativeIntegral++-- | 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++-- | 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 Double where+ 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++-- Integer++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Int.Int32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Int.Int64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Int where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Word.Word64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Integer Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromInteger' when the input is not negative.+instance TryFrom.TryFrom Integer Natural.Natural where+ -- This should use @eitherTryFrom fromNonNegativeIntegral@, but that causes+ -- a bug in GHC 9.0.1. By inlining @fromNonNegativeIntegral@ and replacing+ -- @fromIntegral@ with @fromInteger@, we can work around the bug.+ -- https://mail.haskell.org/pipermail/haskell-cafe/2021-March/133540.html+ 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++-- | 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++-- Word8++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Word.Word16 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Word.Word32 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Word.Word64 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Word where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Natural.Natural where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word8 Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Int.Int16 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Int.Int32 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Int.Int64 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Int where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Integer where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Float where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word8 Double where+ from = fromIntegral++-- Word16++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word16 Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Word.Word32 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Word.Word64 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Word where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Natural.Natural where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word16 Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word16 Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Int.Int32 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Int.Int64 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Int where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Integer where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Float where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word.Word16 Double where+ from = fromIntegral++-- Word32++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word32 Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word32 Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word32 Word.Word64 where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word32 Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word32 Natural.Natural where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word32 Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word32 Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word32 Int.Int32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word32 Int.Int64 where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word32 Int where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word32 Integer where+ from = fromIntegral++-- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.+instance TryFrom.TryFrom Word.Word32 Float where+ tryFrom = Utility.eitherTryFrom $ \s ->+ if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow++-- | Uses 'fromIntegral'.+instance From.From Word.Word32 Double where+ from = fromIntegral++-- Word64++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word64 Natural.Natural where+ -- This should use @fromIntegral@, but that causes a bug in GHC 9.0.1.+ -- https://mail.haskell.org/pipermail/haskell-cafe/2021-March/133540.html+ from s = Utility.unsafeFrom (From.from s :: Integer)++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Int.Int32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Int.Int64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word.Word64 Int where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word.Word64 Integer where+ from = fromIntegral++-- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.+instance TryFrom.TryFrom Word.Word64 Float where+ tryFrom = Utility.eitherTryFrom $ \s ->+ if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow++-- | 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++-- Word++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word Word.Word64 where+ from = fromIntegral++-- | Uses 'fromIntegral'.+instance From.From Word Natural.Natural where+ from = fromIntegral++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word Int.Int32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word Int.Int64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Word Int where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Word Integer where+ from = fromIntegral++-- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.+instance TryFrom.TryFrom Word Float where+ tryFrom = Utility.eitherTryFrom $ \s ->+ if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow++-- | Uses 'fromIntegral' when the input is less than or equal to+-- 9,007,199,254,740,991.+instance TryFrom.TryFrom Word Double where+ tryFrom = Utility.eitherTryFrom $ \s ->+ if (toInteger (maxBound :: Word) <= maxDouble) || (s <= maxDouble)+ then Right $ fromIntegral s+ else Left Exception.Overflow++-- Natural++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Word.Word8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Word.Word16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Word.Word32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Word.Word64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Word where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Int.Int8 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Int.Int16 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Int.Int32 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Int.Int64 where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'Bits.toIntegralSized'.+instance TryFrom.TryFrom Natural.Natural Int where+ tryFrom = Utility.maybeTryFrom Bits.toIntegralSized++-- | Uses 'fromIntegral'.+instance From.From Natural.Natural Integer where+ from = fromIntegral++-- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.+instance TryFrom.TryFrom Natural.Natural Float where+ tryFrom = Utility.eitherTryFrom $ \s ->+ if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow++-- | 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++-- Float++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Int.Int8 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Int.Int16 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Int.Int32 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Int.Int64 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Int where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Rational' when the input is between -16,777,215 and+-- 16,777,215 inclusive.+instance TryFrom.TryFrom Float Integer where+ tryFrom = Utility.eitherTryFrom $ \s -> case Utility.tryVia @Rational s of+ Left e -> Left $ Exception.toException e+ Right t+ | t < -maxFloat -> Left $ Exception.toException Exception.Underflow+ | t > maxFloat -> Left $ Exception.toException Exception.Overflow+ | otherwise -> Right t++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Word.Word8 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Word.Word16 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Word.Word32 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Word.Word64 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Word where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Float Natural.Natural where+ tryFrom = Utility.tryVia @Integer++-- | Uses 'Numeric.floatToDigits' when the input is not NaN or infinity.+instance TryFrom.TryFrom Float Rational where+ tryFrom = Utility.eitherTryFrom realFloatToRational++-- | Uses 'Float.float2Double'.+instance From.From Float Double where+ from = Float.float2Double++-- Double++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Int.Int8 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Int.Int16 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Int.Int32 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Int.Int64 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Int where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Rational' when the input is between -9,007,199,254,740,991+-- and 9,007,199,254,740,991 inclusive.+instance TryFrom.TryFrom Double Integer where+ tryFrom = Utility.eitherTryFrom $ \s -> case Utility.tryVia @Rational s of+ Left e -> Left $ Exception.toException e+ Right t+ | t < -maxDouble -> Left $ Exception.toException Exception.Underflow+ | t > maxDouble -> Left $ Exception.toException Exception.Overflow+ | otherwise -> Right t++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Word.Word8 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Word.Word16 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Word.Word32 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Word.Word64 where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Word where+ tryFrom = Utility.tryVia @Integer++-- | Converts via 'Integer'.+instance TryFrom.TryFrom Double Natural.Natural where+ tryFrom = Utility.tryVia @Integer++-- | Uses 'Numeric.floatToDigits' when the input is not NaN or infinity.+instance TryFrom.TryFrom Double Rational where+ tryFrom = Utility.eitherTryFrom realFloatToRational++-- | Uses 'Float.double2Float'. This necessarily loses some precision.+instance From.From Double Float where+ from = Float.double2Float++-- Ratio++-- | Uses '(Ratio.%)' with a denominator of 1.+instance Integral a => From.From a (Ratio.Ratio a) where+ from = (Ratio.% 1)++-- | 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++-- | Uses 'fromRational'. This necessarily loses some precision.+instance From.From Rational Float where+ from = fromRational++-- | Uses 'fromRational'. This necessarily loses some precision.+instance From.From Rational Double where+ from = fromRational++-- | 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++-- Fixed++-- | Uses 'Fixed.MkFixed'. This means @from \@Integer \@Centi 2@ is @0.02@+-- rather than @2.00@.+instance From.From Integer (Fixed.Fixed a) where+ from = Fixed.MkFixed++-- | Uses 'Fixed.MkFixed'. This means @from \@Centi \@Integer 3.00@ is @300@+-- rather than @3@.+instance From.From (Fixed.Fixed a) Integer where+ from (Fixed.MkFixed t) = t++-- | Uses 'toRational'.+instance Fixed.HasResolution a => From.From (Fixed.Fixed a) Rational where+ from = toRational++-- Complex++-- | Uses '(Complex.:+)' with an imaginary part of 0.+instance Num a => From.From a (Complex.Complex a) where+ from = (Complex.:+ 0)++-- | 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++-- NonEmpty++-- | Uses 'NonEmpty.nonEmpty'.+instance TryFrom.TryFrom [a] (NonEmpty.NonEmpty a) where+ tryFrom = Utility.maybeTryFrom NonEmpty.nonEmpty++-- | Uses 'NonEmpty.toList'.+instance From.From (NonEmpty.NonEmpty a) [a] where+ from = NonEmpty.toList++-- Set++-- | Uses 'Set.fromList'.+instance Ord a => From.From [a] (Set.Set a) where+ from = Set.fromList++-- | Uses 'Set.toAscList'.+instance From.From (Set.Set a) [a] where+ from = Set.toAscList++-- IntSet++-- | Uses 'IntSet.fromList'.+instance From.From [Int] IntSet.IntSet where+ from = IntSet.fromList++-- | Uses 'IntSet.toAscList'.+instance From.From IntSet.IntSet [Int] where+ from = IntSet.toAscList++-- Map++-- | Uses 'Map.fromList'. If there are duplicate keys, later values will+-- overwrite earlier ones.+instance Ord k => From.From [(k, v)] (Map.Map k v) where+ from = Map.fromList++-- | Uses 'Map.toAscList'.+instance From.From (Map.Map k v) [(k, v)] where+ from = Map.toAscList++-- IntMap++-- | Uses 'IntMap.fromList'. If there are duplicate keys, later values will+-- overwrite earlier ones.+instance From.From [(Int, v)] (IntMap.IntMap v) where+ from = IntMap.fromList++-- | Uses 'IntMap.toAscList'.+instance From.From (IntMap.IntMap v) [(Int, v)] where+ from = IntMap.toAscList++-- Seq++-- | Uses 'Seq.fromList'.+instance From.From [a] (Seq.Seq a) where+ from = Seq.fromList++-- | Uses 'Foldable.toList'.+instance From.From (Seq.Seq a) [a] where+ from = Foldable.toList++-- ByteString++-- | Uses 'ByteString.pack'.+instance From.From [Word.Word8] ByteString.ByteString where+ from = ByteString.pack++-- | Uses 'ByteString.unpack'.+instance From.From ByteString.ByteString [Word.Word8] where+ from = ByteString.unpack++-- | Uses 'LazyByteString.fromStrict'.+instance From.From ByteString.ByteString LazyByteString.ByteString where+ from = LazyByteString.fromStrict++-- | Uses 'ShortByteString.toShort'.+instance From.From ByteString.ByteString ShortByteString.ShortByteString where+ from = ShortByteString.toShort++-- | Uses 'Text.decodeUtf8''.+instance TryFrom.TryFrom ByteString.ByteString Text.Text where+ tryFrom = Utility.eitherTryFrom Text.decodeUtf8'++-- | Converts via 'Text.Text'.+instance TryFrom.TryFrom ByteString.ByteString LazyText.Text where+ tryFrom =+ 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++-- LazyByteString++-- | Uses 'LazyByteString.pack'.+instance From.From [Word.Word8] LazyByteString.ByteString where+ from = LazyByteString.pack++-- | Uses 'LazyByteString.unpack'.+instance From.From LazyByteString.ByteString [Word.Word8] where+ from = LazyByteString.unpack++-- | Uses 'LazyByteString.toStrict'.+instance From.From LazyByteString.ByteString ByteString.ByteString where+ from = LazyByteString.toStrict++-- | Uses 'LazyText.decodeUtf8''.+instance TryFrom.TryFrom LazyByteString.ByteString LazyText.Text where+ tryFrom = Utility.eitherTryFrom LazyText.decodeUtf8'++-- | Converts via 'LazyText.Text'.+instance TryFrom.TryFrom LazyByteString.ByteString Text.Text where+ tryFrom =+ 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++-- ShortByteString++-- | Uses 'ShortByteString.pack'.+instance From.From [Word.Word8] ShortByteString.ShortByteString where+ from = ShortByteString.pack++-- | Uses 'ShortByteString.unpack'.+instance From.From ShortByteString.ShortByteString [Word.Word8] where+ from = ShortByteString.unpack++-- | Uses 'ShortByteString.fromShort'.+instance From.From ShortByteString.ShortByteString ByteString.ByteString where+ from = ShortByteString.fromShort++-- Text++-- | Uses 'LazyText.fromStrict'.+instance From.From Text.Text LazyText.Text where+ from = LazyText.fromStrict++-- | Uses 'Text.encodeUtf8'.+instance From.From Text.Text ByteString.ByteString where+ from = Text.encodeUtf8++-- | Converts via 'ByteString.ByteString'.+instance From.From Text.Text LazyByteString.ByteString where+ from = Utility.via @ByteString.ByteString++-- LazyText++-- | Uses 'LazyText.toStrict'.+instance From.From LazyText.Text Text.Text where+ from = LazyText.toStrict++-- | Uses 'LazyText.encodeUtf8'.+instance From.From LazyText.Text LazyByteString.ByteString where+ from = LazyText.encodeUtf8++-- | Converts via 'LazyByteString.ByteString'.+instance From.From LazyText.Text ByteString.ByteString where+ from = Utility.via @LazyByteString.ByteString++-- String++-- | Uses 'Text.pack'. Some 'Char' values cannot be represented in 'Text.Text'+-- and will be replaced with @'\\xFFFD'@.+instance From.From String Text.Text where+ from = Text.pack++-- | Uses 'Text.unpack'.+instance From.From Text.Text String where+ from = Text.unpack++-- | Uses 'LazyText.pack'. Some 'Char' values cannot be represented in+-- 'LazyText.Text' and will be replaced with @'\\xFFFD'@.+instance From.From String LazyText.Text where+ from = LazyText.pack++-- | Uses 'LazyText.unpack'.+instance From.From LazyText.Text String where+ from = LazyText.unpack++-- | Converts via 'Text.Text'.+instance From.From String ByteString.ByteString where+ from = Utility.via @Text.Text++-- | Converts via 'LazyText.Text'.+instance From.From String LazyByteString.ByteString where+ from = Utility.via @LazyText.Text++-- TryFromException++-- | Uses @coerce@.+instance From.From+ (TryFromException.TryFromException source oldTarget)+ (TryFromException.TryFromException source newTarget)++-- Day++-- | Uses 'Time.ModifiedJulianDay'.+instance From.From Integer Time.Day where+ from = Time.ModifiedJulianDay++-- | Uses 'Time.toModifiedJulianDay'.+instance From.From Time.Day Integer where+ from = Time.toModifiedJulianDay++-- DayOfWeek++-- | Uses 'Time.dayOfWeek'.+instance From.From Time.Day Time.DayOfWeek where+ from = Time.dayOfWeek++-- UniversalTime++-- | Uses 'Time.ModJulianDate'.+instance From.From Rational Time.UniversalTime where+ from = Time.ModJulianDate++-- | Uses 'Time.getModJulianDate'.+instance From.From Time.UniversalTime Rational where+ from = Time.getModJulianDate++-- DiffTime++-- | Uses 'realToFrac'.+instance From.From Fixed.Pico Time.DiffTime where+ from = realToFrac++-- | Uses 'realToFrac'.+instance From.From Time.DiffTime Fixed.Pico where+ from = realToFrac++-- NominalDiffTime++-- | Uses 'Time.secondsToNominalDiffTime'.+instance From.From Fixed.Pico Time.NominalDiffTime where+ from = Time.secondsToNominalDiffTime++-- | Uses 'Time.nominalDiffTimeToSeconds'.+instance From.From Time.NominalDiffTime Fixed.Pico where+ from = Time.nominalDiffTimeToSeconds++-- POSIXTime++-- | Uses 'Time.systemToPOSIXTime'.+instance From.From Time.SystemTime Time.POSIXTime where+ from = Time.systemToPOSIXTime++-- | Uses 'Time.utcTimeToPOSIXSeconds'.+instance From.From Time.UTCTime Time.POSIXTime where+ from = Time.utcTimeToPOSIXSeconds++-- | Uses 'Time.posixSecondsToUTCTime'.+instance From.From Time.POSIXTime Time.UTCTime where+ from = Time.posixSecondsToUTCTime++-- SystemTime++-- | Uses 'Time.utcToSystemTime'.+instance From.From Time.UTCTime Time.SystemTime where+ from = Time.utcToSystemTime++-- | Uses 'Time.systemToTAITime'.+instance From.From Time.SystemTime Time.AbsoluteTime where+ from = Time.systemToTAITime++-- | Uses 'Time.systemToUTCTime'.+instance From.From Time.SystemTime Time.UTCTime where+ from = Time.systemToUTCTime++-- TimeOfDay++-- | Uses 'Time.timeToTimeOfDay'.+instance From.From Time.DiffTime Time.TimeOfDay where+ from = Time.timeToTimeOfDay++-- | Uses 'Time.dayFractionToTimeOfDay'.+instance From.From Rational Time.TimeOfDay where+ from = Time.dayFractionToTimeOfDay++-- | Uses 'Time.timeOfDayToTime'.+instance From.From Time.TimeOfDay Time.DiffTime where+ from = Time.timeOfDayToTime++-- | Uses 'Time.timeOfDayToDayFraction'.+instance From.From Time.TimeOfDay Rational where+ from = Time.timeOfDayToDayFraction++-- CalendarDiffTime++-- | Uses 'Time.calendarTimeDays'.+instance From.From Time.CalendarDiffDays Time.CalendarDiffTime where+ from = Time.calendarTimeDays++-- | Uses 'Time.calendarTimeTime'.+instance From.From Time.NominalDiffTime Time.CalendarDiffTime where+ from = Time.calendarTimeTime++-- ZonedTime++-- | Uses 'Time.zonedTimeToUTC'.+instance From.From Time.ZonedTime Time.UTCTime where+ from = Time.zonedTimeToUTC++--++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++overPositive :: (Eq a, Num a, Num b) => (a -> b) -> a -> b+overPositive f x = if signum x == -1 then -(f (-x)) else f x++fromDigits :: [Int] -> Int -> (Integer, Integer)+fromDigits ds e =+ List.foldl' (\(a, n) d -> (a * 10 + toInteger d, n - 1)) (0, toInteger e) ds++makeRational :: Integer -> Integer -> Rational+makeRational d e = toRational d * 10 ^^ e++fromNonNegativeIntegral+ :: (Integral s, Num t) => s -> Either Exception.ArithException t+fromNonNegativeIntegral x =+ if x < 0 then Left Exception.Underflow else Right $ fromIntegral x++-- | The maximum integral value that can be unambiguously represented as a+-- 'Float'. Equal to 16,777,215.+maxFloat :: Num a => a+maxFloat = 16777215++-- | The maximum integral value that can be unambiguously represented as a+-- 'Double'. Equal to 9,007,199,254,740,991.+maxDouble :: Num a => a+maxDouble = 9007199254740991
+ source/library/Witch/TryFrom.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE MultiParamTypeClasses #-}++module Witch.TryFrom where++import qualified Witch.TryFromException as TryFromException++-- | This type class is for converting values from some @source@ type into+-- some other @target@ type. The constraint @'TryFrom' source target@ means+-- that you may be able to convert from a value of type @source@ into a value+-- of type @target@, but that conversion may fail at runtime.+--+-- This type class is for conversions that can sometimes fail. If your+-- conversion always succeeds, consider implementing @From@ instead.+class TryFrom source target where+ -- | This method implements the conversion of a value between types. At call+ -- sites you may want to use @tryInto@ instead.+ --+ -- > -- Avoid this:+ -- > tryFrom (x :: s)+ -- >+ -- > -- Prefer this:+ -- > tryFrom @s+ --+ -- Consider using @maybeTryFrom@ or @eitherTryFrom@ to implement this+ -- method.+ tryFrom :: source -> Either (TryFromException.TryFromException source target) target
+ source/library/Witch/TryFromException.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Witch.TryFromException where++import qualified Control.Exception as Exception+import qualified Data.Proxy as Proxy+import qualified Data.Typeable as Typeable++-- | This exception is thrown when a @TryFrom@ conversion fails. It has the+-- original @source@ value that caused the failure and it knows the @target@+-- 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)++instance+ ( 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++instance+ ( Show source+ , Typeable.Typeable source+ , Typeable.Typeable target+ ) => Exception.Exception (TryFromException source target)
+ source/library/Witch/Utility.hs view
@@ -0,0 +1,199 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Witch.Utility where++import qualified Control.Exception as Exception+import qualified Data.Coerce as Coerce+import qualified Data.Typeable as Typeable+import qualified GHC.Stack as Stack+import qualified Witch.From as From+import qualified Witch.TryFrom as TryFrom+import qualified Witch.TryFromException as TryFromException++-- | This is the same as 'id'. This can be an ergonomic way to pin down a+-- polymorphic type in a function pipeline. For example:+--+-- > -- Avoid this:+-- > f . (\ x -> x :: Int) . g+-- >+-- > -- Prefer this:+-- > f . as @Int . g+as :: forall source . source -> source+as = id++-- | This is the same as 'From.from' except that the type variables are in the+-- opposite order.+--+-- > -- Avoid this:+-- > from x :: t+-- >+-- > -- Prefer this:+-- > into @t x+into :: forall target source . From.From source target => source -> target+into = From.from++-- | This function converts from some @source@ type into some @target@ type,+-- applies the given function, then converts back into the @source@ type. This+-- is useful when you have two types that are isomorphic but some function+-- that only works with one of them.+--+-- > -- Avoid this:+-- > from @t . f . into @t+-- >+-- > -- Prefer this:+-- > over @t f+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@+-- type, and then converts that into some @target@ type. Usually this is used+-- when writing 'From.From' instances. Sometimes this can be used to work+-- around the lack of an instance that should probably exist.+--+-- > -- Avoid this:+-- > from @u . into @u+-- >+-- > -- Prefer this:+-- > via @u+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+-- in the opposite order.+--+-- > -- Avoid this:+-- > tryFrom x :: Either (TryFromException s t) t+-- >+-- > -- Prefer this:+-- > tryInto @t x+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'+-- instances instead. This function is especially convenient because juggling+-- the types in the 'TryFromException.TryFromException' can be tedious.+--+-- > -- Avoid this:+-- > case tryInto @u x of+-- > Left (TryFromException _ e) -> Left $ TryFromException x e+-- > Right y -> case tryFrom @u y of+-- > Left (TryFromException _ e) -> Left $ TryFromException x e+-- > Right z -> Right z+-- >+-- > -- 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 s = case TryFrom.tryFrom s of+ Left e -> Left $ withTarget e+ Right u -> case TryFrom.tryFrom (u :: through) of+ Left e -> Left $ withSource s e+ Right t -> Right t++-- | This function can be used to implement 'TryFrom.tryFrom' with a function+-- that returns 'Maybe'. For example:+--+-- > -- Avoid this:+-- > tryFrom s = case f s of+-- > Nothing -> Left $ TryFromException s Nothing+-- > Just t -> Right t+-- >+-- > -- Prefer this:+-- > tryFrom = maybeTryFrom f+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++-- | This function can be used to implement 'TryFrom.tryFrom' with a function+-- that returns 'Either'. For example:+--+-- > -- Avoid this:+-- > tryFrom s = case f s of+-- > Left e -> Left . TryFromException s . Just $ toException e+-- > Right t -> Right t+-- >+-- > -- Prefer this:+-- > tryFrom = eitherTryFrom f+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+ Right t -> Right t++-- | This function is like 'TryFrom.tryFrom' except that it will throw an+-- impure exception if the conversion fails.+--+-- > -- Avoid this:+-- > either throw id . tryFrom @s+-- >+-- > -- 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 = either Exception.throw id . TryFrom.tryFrom++-- | This function is like 'tryInto' except that it will throw an impure+-- exception if the conversion fails.+--+-- > -- Avoid this:+-- > either throw id . tryInto @t+-- >+-- > -- 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 = unsafeFrom++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 = Coerce.coerce
+ source/test-suite/Main.hs view
@@ -0,0 +1,1981 @@+{-# 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
− src/ghc-8.10/Witch/Lift.hs
@@ -1,48 +0,0 @@-{-# LANGUAGE ExplicitForAll #-}--module Witch.Lift where--import qualified Data.Typeable as Typeable-import qualified Language.Haskell.TH.Syntax as TH-import qualified Witch.TryFrom as TryFrom-import qualified Witch.Utility as Utility---- | This is like 'Utility.unsafeFrom' except that it works at compile time--- rather than runtime.------ > -- Avoid this:--- > unsafeFrom @s "some literal"--- >--- > -- 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 = TH.liftTyped . Utility.unsafeFrom---- | This is like 'Utility.unsafeInto' except that it works at compile time--- rather than runtime.------ > -- Avoid this:--- > unsafeInto @t "some literal"--- >--- > -- 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 = liftedFrom
− src/ghc-8.8/Witch/Lift.hs
@@ -1,48 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}--module Witch.Lift where--import qualified Data.Typeable as Typeable-import qualified Language.Haskell.TH.Syntax as TH-import qualified Witch.TryFrom as TryFrom-import qualified Witch.Utility as Utility---- | This is like 'Utility.unsafeFrom' except that it works at compile time--- rather than runtime.------ > -- Avoid this:--- > unsafeFrom @s "some literal"--- >--- > -- 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 s = TH.unsafeTExpCoerce $ TH.lift (Utility.unsafeFrom s :: target)---- | This is like 'Utility.unsafeInto' except that it works at compile time--- rather than runtime.------ > -- Avoid this:--- > unsafeInto @t "some literal"--- >--- > -- 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 = liftedFrom
− src/ghc-9.0/Witch/Lift.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE ExplicitForAll #-}--module Witch.Lift where--import qualified Data.Typeable as Typeable-import qualified Language.Haskell.TH.Syntax as TH-import qualified Witch.TryFrom as TryFrom-import qualified Witch.Utility as Utility---- | This is like 'Utility.unsafeFrom' except that it works at compile time--- rather than runtime.------ > -- Avoid this:--- > unsafeFrom @s "some literal"--- >--- > -- 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 = TH.liftTyped . Utility.unsafeFrom---- | This is like 'Utility.unsafeInto' except that it works at compile time--- rather than runtime.------ > -- Avoid this:--- > unsafeInto @t "some literal"--- >--- > -- 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 = liftedFrom
− src/lib/Witch.hs
@@ -1,258 +0,0 @@--- | The Witch package is a library that allows you to confidently convert--- values between various types. This module exports everything you need to--- perform conversions or define your own. It is designed to be imported--- unqualified, so getting started is as easy as:------ >>> import Witch------ In typical usage, the functions that you will use most often are--- 'Witch.Utility.into' for conversions that always succeed and--- 'Witch.Utility.tryInto' for conversions that sometimes fail.-module Witch- ( -- * Type classes-- -- ** From- Witch.From.From(from)- , Witch.Utility.into-- -- ** TryFrom- , Witch.TryFrom.TryFrom(tryFrom)- , Witch.Utility.tryInto-- -- * Data types- , Witch.TryFromException.TryFromException(..)-- -- * 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-- -- ** 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-- -- * Notes-- -- ** 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.-- -- ** 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-- -- ** 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 ()-import qualified Witch.Lift-import qualified Witch.TryFrom-import qualified Witch.TryFromException-import qualified Witch.Utility
− src/lib/Witch/From.hs
@@ -1,36 +0,0 @@-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE MultiParamTypeClasses #-}--module Witch.From where--import qualified Data.Coerce as Coerce---- | This type class is for converting values from some @source@ type into--- some other @target@ type. The constraint @'From' source target@ means that--- you can convert from a value of type @source@ into a value of type--- @target@.------ This type class is for conversions that always succeed. If your conversion--- sometimes fails, consider implementing @TryFrom@ instead.-class From source target where- -- | This method implements the conversion of a value between types. At call- -- sites you may prefer to use @into@ instead.- --- -- > -- Avoid this:- -- > from (x :: s)- -- >- -- > -- Prefer this:- -- > from @s x- --- -- The default implementation of this method simply calls 'Coerce.coerce',- -- which works for types that have the same runtime representation. This- -- means that for @newtype@s you do not need to implement this method at- -- all. For example:- --- -- >>> newtype Name = Name String- -- >>> instance From Name String- -- >>> instance From String Name- from :: source -> target-- default from :: Coerce.Coercible source target => source -> target- from = Coerce.coerce
− src/lib/Witch/Instances.hs
@@ -1,1291 +0,0 @@-{-# OPTIONS_GHC -Wno-orphans #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}--module Witch.Instances where--import qualified Control.Exception as Exception-import qualified Data.Bits as Bits-import qualified Data.ByteString as ByteString-import qualified Data.ByteString.Lazy as LazyByteString-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 as List-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.Encoding as Text-import qualified Data.Text.Lazy as LazyText-import qualified Data.Text.Lazy.Encoding 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.Float as Float-import qualified Numeric-import qualified Numeric.Natural as Natural-import qualified Witch.From as From-import qualified Witch.TryFrom as TryFrom-import qualified Witch.TryFromException as TryFromException-import qualified Witch.Utility as Utility---- | Uses 'id'.-instance From.From a a where- from = id---- Int8---- | Uses 'fromIntegral'.-instance From.From Int.Int8 Int.Int16 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int8 Int.Int32 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int8 Int.Int64 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int8 Int where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int8 Integer where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int8 Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int8 Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int8 Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int8 Word.Word64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int8 Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral' when the input is not negative.-instance TryFrom.TryFrom Int.Int8 Natural.Natural where- tryFrom = Utility.eitherTryFrom fromNonNegativeIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int8 Float where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int8 Double where- from = fromIntegral---- Int16---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int16 Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Int.Int16 Int.Int32 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int16 Int.Int64 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int16 Int where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int16 Integer where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int16 Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int16 Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int16 Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int16 Word.Word64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int16 Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral' when the input is not negative.-instance TryFrom.TryFrom Int.Int16 Natural.Natural where- tryFrom = Utility.eitherTryFrom fromNonNegativeIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int16 Float where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int.Int16 Double where- from = fromIntegral---- Int32---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int32 Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int32 Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Int.Int32 Int.Int64 where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int32 Int where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Int.Int32 Integer where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int32 Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int32 Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int32 Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int32 Word.Word64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int32 Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral' when the input is not negative.-instance TryFrom.TryFrom Int.Int32 Natural.Natural where- tryFrom = Utility.eitherTryFrom fromNonNegativeIntegral---- | 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---- | Uses 'fromIntegral'.-instance From.From Int.Int32 Double where- from = fromIntegral---- Int64---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Int.Int32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Int where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Int.Int64 Integer where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Word.Word64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int.Int64 Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral' when the input is not negative.-instance TryFrom.TryFrom Int.Int64 Natural.Natural where- -- This should use @eitherTryFrom fromNonNegativeIntegral@, but that causes- -- a bug in GHC 9.0.1.- -- https://mail.haskell.org/pipermail/haskell-cafe/2021-March/133540.html- tryFrom =- Utility.eitherTryFrom $ \s -> TryFrom.tryFrom (From.from s :: Integer)---- | 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---- | 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---- Int---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int Int.Int32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Int Int.Int64 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Int Integer where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int Word.Word64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Int Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral' when the input is not negative.-instance TryFrom.TryFrom Int Natural.Natural where- tryFrom = Utility.eitherTryFrom fromNonNegativeIntegral---- | 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---- | 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 Double where- 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---- Integer---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Int.Int32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Int.Int64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Int where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Word.Word64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Integer Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromInteger' when the input is not negative.-instance TryFrom.TryFrom Integer Natural.Natural where- -- This should use @eitherTryFrom fromNonNegativeIntegral@, but that causes- -- a bug in GHC 9.0.1. By inlining @fromNonNegativeIntegral@ and replacing- -- @fromIntegral@ with @fromInteger@, we can work around the bug.- -- https://mail.haskell.org/pipermail/haskell-cafe/2021-March/133540.html- 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---- | 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---- Word8---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Word.Word16 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Word.Word32 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Word.Word64 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Word where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Natural.Natural where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word8 Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Int.Int16 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Int.Int32 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Int.Int64 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Int where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Integer where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Float where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word8 Double where- from = fromIntegral---- Word16---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word16 Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Word.Word32 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Word.Word64 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Word where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Natural.Natural where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word16 Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word16 Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Int.Int32 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Int.Int64 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Int where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Integer where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Float where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word.Word16 Double where- from = fromIntegral---- Word32---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word32 Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word32 Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word32 Word.Word64 where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word32 Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word32 Natural.Natural where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word32 Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word32 Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word32 Int.Int32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word32 Int.Int64 where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word32 Int where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word32 Integer where- from = fromIntegral---- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.-instance TryFrom.TryFrom Word.Word32 Float where- tryFrom = Utility.eitherTryFrom $ \s ->- if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow---- | Uses 'fromIntegral'.-instance From.From Word.Word32 Double where- from = fromIntegral---- Word64---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word64 Natural.Natural where- -- This should use @fromIntegral@, but that causes a bug in GHC 9.0.1.- -- https://mail.haskell.org/pipermail/haskell-cafe/2021-March/133540.html- from s = Utility.unsafeFrom (From.from s :: Integer)---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Int.Int32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Int.Int64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word.Word64 Int where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word.Word64 Integer where- from = fromIntegral---- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.-instance TryFrom.TryFrom Word.Word64 Float where- tryFrom = Utility.eitherTryFrom $ \s ->- if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow---- | 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---- Word---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word Word.Word64 where- from = fromIntegral---- | Uses 'fromIntegral'.-instance From.From Word Natural.Natural where- from = fromIntegral---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word Int.Int32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word Int.Int64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Word Int where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Word Integer where- from = fromIntegral---- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.-instance TryFrom.TryFrom Word Float where- tryFrom = Utility.eitherTryFrom $ \s ->- if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow---- | Uses 'fromIntegral' when the input is less than or equal to--- 9,007,199,254,740,991.-instance TryFrom.TryFrom Word Double where- tryFrom = Utility.eitherTryFrom $ \s ->- if (toInteger (maxBound :: Word) <= maxDouble) || (s <= maxDouble)- then Right $ fromIntegral s- else Left Exception.Overflow---- Natural---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Word.Word8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Word.Word16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Word.Word32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Word.Word64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Word where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Int.Int8 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Int.Int16 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Int.Int32 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Int.Int64 where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'Bits.toIntegralSized'.-instance TryFrom.TryFrom Natural.Natural Int where- tryFrom = Utility.maybeTryFrom Bits.toIntegralSized---- | Uses 'fromIntegral'.-instance From.From Natural.Natural Integer where- from = fromIntegral---- | Uses 'fromIntegral' when the input is less than or equal to 16,777,215.-instance TryFrom.TryFrom Natural.Natural Float where- tryFrom = Utility.eitherTryFrom $ \s ->- if s <= maxFloat then Right $ fromIntegral s else Left Exception.Overflow---- | 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---- Float---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Int.Int8 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Int.Int16 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Int.Int32 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Int.Int64 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Int where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Rational' when the input is between -16,777,215 and--- 16,777,215 inclusive.-instance TryFrom.TryFrom Float Integer where- tryFrom = Utility.eitherTryFrom $ \s -> case Utility.tryVia @Rational s of- Left e -> Left $ Exception.toException e- Right t- | t < -maxFloat -> Left $ Exception.toException Exception.Underflow- | t > maxFloat -> Left $ Exception.toException Exception.Overflow- | otherwise -> Right t---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Word.Word8 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Word.Word16 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Word.Word32 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Word.Word64 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Word where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Float Natural.Natural where- tryFrom = Utility.tryVia @Integer---- | Uses 'Numeric.floatToDigits' when the input is not NaN or infinity.-instance TryFrom.TryFrom Float Rational where- tryFrom = Utility.eitherTryFrom realFloatToRational---- | Uses 'Float.float2Double'.-instance From.From Float Double where- from = Float.float2Double---- Double---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Int.Int8 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Int.Int16 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Int.Int32 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Int.Int64 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Int where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Rational' when the input is between -9,007,199,254,740,991--- and 9,007,199,254,740,991 inclusive.-instance TryFrom.TryFrom Double Integer where- tryFrom = Utility.eitherTryFrom $ \s -> case Utility.tryVia @Rational s of- Left e -> Left $ Exception.toException e- Right t- | t < -maxDouble -> Left $ Exception.toException Exception.Underflow- | t > maxDouble -> Left $ Exception.toException Exception.Overflow- | otherwise -> Right t---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Word.Word8 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Word.Word16 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Word.Word32 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Word.Word64 where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Word where- tryFrom = Utility.tryVia @Integer---- | Converts via 'Integer'.-instance TryFrom.TryFrom Double Natural.Natural where- tryFrom = Utility.tryVia @Integer---- | Uses 'Numeric.floatToDigits' when the input is not NaN or infinity.-instance TryFrom.TryFrom Double Rational where- tryFrom = Utility.eitherTryFrom realFloatToRational---- | Uses 'Float.double2Float'. This necessarily loses some precision.-instance From.From Double Float where- from = Float.double2Float---- Ratio---- | Uses '(Ratio.%)' with a denominator of 1.-instance Integral a => From.From a (Ratio.Ratio a) where- from = (Ratio.% 1)---- | 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---- | Uses 'fromRational'. This necessarily loses some precision.-instance From.From Rational Float where- from = fromRational---- | Uses 'fromRational'. This necessarily loses some precision.-instance From.From Rational Double where- from = fromRational---- | 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---- Fixed---- | Uses 'Fixed.MkFixed'. This means @from \@Integer \@Centi 2@ is @0.02@--- rather than @2.00@.-instance From.From Integer (Fixed.Fixed a) where- from = Fixed.MkFixed---- | Uses 'Fixed.MkFixed'. This means @from \@Centi \@Integer 3.00@ is @300@--- rather than @3@.-instance From.From (Fixed.Fixed a) Integer where- from (Fixed.MkFixed t) = t---- | Uses 'toRational'.-instance Fixed.HasResolution a => From.From (Fixed.Fixed a) Rational where- from = toRational---- Complex---- | Uses '(Complex.:+)' with an imaginary part of 0.-instance Num a => From.From a (Complex.Complex a) where- from = (Complex.:+ 0)---- | 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---- NonEmpty---- | Uses 'NonEmpty.nonEmpty'.-instance TryFrom.TryFrom [a] (NonEmpty.NonEmpty a) where- tryFrom = Utility.maybeTryFrom NonEmpty.nonEmpty---- | Uses 'NonEmpty.toList'.-instance From.From (NonEmpty.NonEmpty a) [a] where- from = NonEmpty.toList---- Set---- | Uses 'Set.fromList'.-instance Ord a => From.From [a] (Set.Set a) where- from = Set.fromList---- | Uses 'Set.toAscList'.-instance From.From (Set.Set a) [a] where- from = Set.toAscList---- IntSet---- | Uses 'IntSet.fromList'.-instance From.From [Int] IntSet.IntSet where- from = IntSet.fromList---- | Uses 'IntSet.toAscList'.-instance From.From IntSet.IntSet [Int] where- from = IntSet.toAscList---- Map---- | Uses 'Map.fromList'. If there are duplicate keys, later values will--- overwrite earlier ones.-instance Ord k => From.From [(k, v)] (Map.Map k v) where- from = Map.fromList---- | Uses 'Map.toAscList'.-instance From.From (Map.Map k v) [(k, v)] where- from = Map.toAscList---- IntMap---- | Uses 'IntMap.fromList'. If there are duplicate keys, later values will--- overwrite earlier ones.-instance From.From [(Int, v)] (IntMap.IntMap v) where- from = IntMap.fromList---- | Uses 'IntMap.toAscList'.-instance From.From (IntMap.IntMap v) [(Int, v)] where- from = IntMap.toAscList---- Seq---- | Uses 'Seq.fromList'.-instance From.From [a] (Seq.Seq a) where- from = Seq.fromList---- | Uses 'Foldable.toList'.-instance From.From (Seq.Seq a) [a] where- from = Foldable.toList---- ByteString---- | Uses 'ByteString.pack'.-instance From.From [Word.Word8] ByteString.ByteString where- from = ByteString.pack---- | Uses 'ByteString.unpack'.-instance From.From ByteString.ByteString [Word.Word8] where- from = ByteString.unpack---- | Uses 'LazyByteString.fromStrict'.-instance From.From ByteString.ByteString LazyByteString.ByteString where- from = LazyByteString.fromStrict---- | Uses 'ShortByteString.toShort'.-instance From.From ByteString.ByteString ShortByteString.ShortByteString where- from = ShortByteString.toShort---- | Uses 'Text.decodeUtf8''.-instance TryFrom.TryFrom ByteString.ByteString Text.Text where- tryFrom = Utility.eitherTryFrom Text.decodeUtf8'---- | Converts via 'Text.Text'.-instance TryFrom.TryFrom ByteString.ByteString LazyText.Text where- tryFrom =- 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---- LazyByteString---- | Uses 'LazyByteString.pack'.-instance From.From [Word.Word8] LazyByteString.ByteString where- from = LazyByteString.pack---- | Uses 'LazyByteString.unpack'.-instance From.From LazyByteString.ByteString [Word.Word8] where- from = LazyByteString.unpack---- | Uses 'LazyByteString.toStrict'.-instance From.From LazyByteString.ByteString ByteString.ByteString where- from = LazyByteString.toStrict---- | Uses 'LazyText.decodeUtf8''.-instance TryFrom.TryFrom LazyByteString.ByteString LazyText.Text where- tryFrom = Utility.eitherTryFrom LazyText.decodeUtf8'---- | Converts via 'LazyText.Text'.-instance TryFrom.TryFrom LazyByteString.ByteString Text.Text where- tryFrom =- 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---- ShortByteString---- | Uses 'ShortByteString.pack'.-instance From.From [Word.Word8] ShortByteString.ShortByteString where- from = ShortByteString.pack---- | Uses 'ShortByteString.unpack'.-instance From.From ShortByteString.ShortByteString [Word.Word8] where- from = ShortByteString.unpack---- | Uses 'ShortByteString.fromShort'.-instance From.From ShortByteString.ShortByteString ByteString.ByteString where- from = ShortByteString.fromShort---- Text---- | Uses 'LazyText.fromStrict'.-instance From.From Text.Text LazyText.Text where- from = LazyText.fromStrict---- | Uses 'Text.encodeUtf8'.-instance From.From Text.Text ByteString.ByteString where- from = Text.encodeUtf8---- | Converts via 'ByteString.ByteString'.-instance From.From Text.Text LazyByteString.ByteString where- from = Utility.via @ByteString.ByteString---- LazyText---- | Uses 'LazyText.toStrict'.-instance From.From LazyText.Text Text.Text where- from = LazyText.toStrict---- | Uses 'LazyText.encodeUtf8'.-instance From.From LazyText.Text LazyByteString.ByteString where- from = LazyText.encodeUtf8---- | Converts via 'LazyByteString.ByteString'.-instance From.From LazyText.Text ByteString.ByteString where- from = Utility.via @LazyByteString.ByteString---- String---- | Uses 'Text.pack'. Some 'Char' values cannot be represented in 'Text.Text'--- and will be replaced with @'\\xFFFD'@.-instance From.From String Text.Text where- from = Text.pack---- | Uses 'Text.unpack'.-instance From.From Text.Text String where- from = Text.unpack---- | Uses 'LazyText.pack'. Some 'Char' values cannot be represented in--- 'LazyText.Text' and will be replaced with @'\\xFFFD'@.-instance From.From String LazyText.Text where- from = LazyText.pack---- | Uses 'LazyText.unpack'.-instance From.From LazyText.Text String where- from = LazyText.unpack---- | Converts via 'Text.Text'.-instance From.From String ByteString.ByteString where- from = Utility.via @Text.Text---- | Converts via 'LazyText.Text'.-instance From.From String LazyByteString.ByteString where- from = Utility.via @LazyText.Text---- TryFromException---- | Uses @coerce@.-instance From.From- (TryFromException.TryFromException s u)- (TryFromException.TryFromException s t)---- Day---- | Uses 'Time.ModifiedJulianDay'.-instance From.From Integer Time.Day where- from = Time.ModifiedJulianDay---- | Uses 'Time.toModifiedJulianDay'.-instance From.From Time.Day Integer where- from = Time.toModifiedJulianDay---- DayOfWeek---- | Uses 'Time.dayOfWeek'.-instance From.From Time.Day Time.DayOfWeek where- from = Time.dayOfWeek---- UniversalTime---- | Uses 'Time.ModJulianDate'.-instance From.From Rational Time.UniversalTime where- from = Time.ModJulianDate---- | Uses 'Time.getModJulianDate'.-instance From.From Time.UniversalTime Rational where- from = Time.getModJulianDate---- DiffTime---- | Uses 'realToFrac'.-instance From.From Fixed.Pico Time.DiffTime where- from = realToFrac---- | Uses 'realToFrac'.-instance From.From Time.DiffTime Fixed.Pico where- from = realToFrac---- NominalDiffTime---- | Uses 'Time.secondsToNominalDiffTime'.-instance From.From Fixed.Pico Time.NominalDiffTime where- from = Time.secondsToNominalDiffTime---- | Uses 'Time.nominalDiffTimeToSeconds'.-instance From.From Time.NominalDiffTime Fixed.Pico where- from = Time.nominalDiffTimeToSeconds---- POSIXTime---- | Uses 'Time.systemToPOSIXTime'.-instance From.From Time.SystemTime Time.POSIXTime where- from = Time.systemToPOSIXTime---- | Uses 'Time.utcTimeToPOSIXSeconds'.-instance From.From Time.UTCTime Time.POSIXTime where- from = Time.utcTimeToPOSIXSeconds---- | Uses 'Time.posixSecondsToUTCTime'.-instance From.From Time.POSIXTime Time.UTCTime where- from = Time.posixSecondsToUTCTime---- SystemTime---- | Uses 'Time.utcToSystemTime'.-instance From.From Time.UTCTime Time.SystemTime where- from = Time.utcToSystemTime---- | Uses 'Time.systemToTAITime'.-instance From.From Time.SystemTime Time.AbsoluteTime where- from = Time.systemToTAITime---- | Uses 'Time.systemToUTCTime'.-instance From.From Time.SystemTime Time.UTCTime where- from = Time.systemToUTCTime---- TimeOfDay---- | Uses 'Time.timeToTimeOfDay'.-instance From.From Time.DiffTime Time.TimeOfDay where- from = Time.timeToTimeOfDay---- | Uses 'Time.dayFractionToTimeOfDay'.-instance From.From Rational Time.TimeOfDay where- from = Time.dayFractionToTimeOfDay---- | Uses 'Time.timeOfDayToTime'.-instance From.From Time.TimeOfDay Time.DiffTime where- from = Time.timeOfDayToTime---- | Uses 'Time.timeOfDayToDayFraction'.-instance From.From Time.TimeOfDay Rational where- from = Time.timeOfDayToDayFraction---- CalendarDiffTime---- | Uses 'Time.calendarTimeDays'.-instance From.From Time.CalendarDiffDays Time.CalendarDiffTime where- from = Time.calendarTimeDays---- | Uses 'Time.calendarTimeTime'.-instance From.From Time.NominalDiffTime Time.CalendarDiffTime where- from = Time.calendarTimeTime---- ZonedTime---- | Uses 'Time.zonedTimeToUTC'.-instance From.From Time.ZonedTime Time.UTCTime where- from = Time.zonedTimeToUTC------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--overPositive :: (Eq a, Num a, Num b) => (a -> b) -> a -> b-overPositive f x = if signum x == -1 then -(f (-x)) else f x--fromDigits :: [Int] -> Int -> (Integer, Integer)-fromDigits ds e =- List.foldl' (\(a, n) d -> (a * 10 + toInteger d, n - 1)) (0, toInteger e) ds--makeRational :: Integer -> Integer -> Rational-makeRational d e = toRational d * 10 ^^ e--fromNonNegativeIntegral- :: (Integral s, Num t) => s -> Either Exception.ArithException t-fromNonNegativeIntegral x =- if x < 0 then Left Exception.Underflow else Right $ fromIntegral x---- | The maximum integral value that can be unambiguously represented as a--- 'Float'. Equal to 16,777,215.-maxFloat :: Num a => a-maxFloat = 16777215---- | The maximum integral value that can be unambiguously represented as a--- 'Double'. Equal to 9,007,199,254,740,991.-maxDouble :: Num a => a-maxDouble = 9007199254740991
− src/lib/Witch/TryFrom.hs
@@ -1,26 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}--module Witch.TryFrom where--import qualified Witch.TryFromException as TryFromException---- | This type class is for converting values from some @source@ type into--- some other @target@ type. The constraint @'TryFrom' source target@ means--- that you may be able to convert from a value of type @source@ into a value--- of type @target@, but that conversion may fail at runtime.------ This type class is for conversions that can sometimes fail. If your--- conversion always succeeds, consider implementing @From@ instead.-class TryFrom source target where- -- | This method implements the conversion of a value between types. At call- -- sites you may want to use @tryInto@ instead.- --- -- > -- Avoid this:- -- > tryFrom (x :: s)- -- >- -- > -- Prefer this:- -- > tryFrom @s- --- -- Consider using @maybeTryFrom@ or @eitherTryFrom@ to implement this- -- method.- tryFrom :: source -> Either (TryFromException.TryFromException source target) target
− src/lib/Witch/TryFromException.hs
@@ -1,38 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}--module Witch.TryFromException where--import qualified Control.Exception as Exception-import qualified Data.Proxy as Proxy-import qualified Data.Typeable as Typeable---- | This exception is thrown when a @TryFrom@ conversion fails. It has the--- original @source@ value that caused the failure and it knows the @target@--- 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)--instance- ( 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--instance- ( Show source- , Typeable.Typeable source- , Typeable.Typeable target- ) => Exception.Exception (TryFromException source target)
− src/lib/Witch/Utility.hs
@@ -1,187 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Witch.Utility where--import qualified Control.Exception as Exception-import qualified Data.Typeable as Typeable-import qualified GHC.Stack as Stack-import qualified Witch.From as From-import qualified Witch.TryFrom as TryFrom-import qualified Witch.TryFromException as TryFromException---- | This is the same as 'id'. This can be an ergonomic way to pin down a--- polymorphic type in a function pipeline. For example:------ > -- Avoid this:--- > f . (\ x -> x :: Int) . g--- >--- > -- Prefer this:--- > f . as @Int . g-as :: forall source . source -> source-as = id---- | This is the same as 'From.from' except that the type variables are in the--- opposite order.------ > -- Avoid this:--- > from x :: t--- >--- > -- Prefer this:--- > into @t x-into :: forall target source . From.From source target => source -> target-into = From.from---- | This function converts from some @source@ type into some @target@ type,--- applies the given function, then converts back into the @source@ type. This--- is useful when you have two types that are isomorphic but some function--- that only works with one of them.------ > -- Avoid this:--- > from @t . f . into @t--- >--- > -- Prefer this:--- > over @t f-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@--- type, and then converts that into some @target@ type. Usually this is used--- when writing 'From.From' instances. Sometimes this can be used to work--- around the lack of an instance that should probably exist.------ > -- Avoid this:--- > from @u . into @u--- >--- > -- Prefer this:--- > via @u-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--- in the opposite order.------ > -- Avoid this:--- > tryFrom x :: Either (TryFromException s t) t--- >--- > -- Prefer this:--- > tryInto @t x-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'--- instances instead. This function is especially convenient because juggling--- the types in the 'TryFromException.TryFromException' can be tedious.------ > -- Avoid this:--- > case tryInto @u x of--- > Left (TryFromException _ e) -> Left $ TryFromException x e--- > Right y -> case tryFrom @u y of--- > Left (TryFromException _ e) -> Left $ TryFromException x e--- > Right z -> Right z--- >--- > -- 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 s = case TryFrom.tryFrom s of- Left (TryFromException.TryFromException _ e) ->- Left $ TryFromException.TryFromException s e- Right u -> case TryFrom.tryFrom (u :: through) of- Left (TryFromException.TryFromException _ e) ->- Left $ TryFromException.TryFromException s e- Right t -> Right t---- | This function can be used to implement 'TryFrom.tryFrom' with a function--- that returns 'Maybe'. For example:------ > -- Avoid this:--- > tryFrom s = case f s of--- > Nothing -> Left $ TryFromException s Nothing--- > Just t -> Right t--- >--- > -- Prefer this:--- > tryFrom = maybeTryFrom f-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---- | This function can be used to implement 'TryFrom.tryFrom' with a function--- that returns 'Either'. For example:------ > -- Avoid this:--- > tryFrom s = case f s of--- > Left e -> Left . TryFromException s . Just $ toException e--- > Right t -> Right t--- >--- > -- Prefer this:--- > tryFrom = eitherTryFrom f-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- Right t -> Right t---- | This function is like 'TryFrom.tryFrom' except that it will throw an--- impure exception if the conversion fails.------ > -- Avoid this:--- > either throw id . tryFrom @s--- >--- > -- 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 = either Exception.throw id . TryFrom.tryFrom---- | This function is like 'tryInto' except that it will throw an impure--- exception if the conversion fails.------ > -- Avoid this:--- > either throw id . tryInto @t--- >--- > -- 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 = unsafeFrom
− src/test/Main.hs
@@ -1,1931 +0,0 @@-{-# 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
witch.cabal view
@@ -1,15 +1,15 @@ cabal-version: 2.2 name: witch-version: 0.3.4.2+version: 1.0.0.1 synopsis: Convert values from one type into another. description: Witch converts values from one type into another. build-type: Simple category: Data extra-source-files: CHANGELOG.markdown README.markdown-license-file: LICENSE.txt-license: ISC+license-file: LICENSE.markdown+license: MIT maintainer: Taylor Fausak source-repository head@@ -21,11 +21,12 @@ description: Enables @-Werror@, which turns warnings into errors. manual: True -common basics+common library build-depends: , base >= 4.10.0 && < 4.17 , bytestring >= 0.10.8 && < 0.12 , containers >= 0.5.10 && < 0.7+ , template-haskell >= 2.12.0 && < 2.19 , text >= 1.2.3 && < 1.3 , time >= 1.9.1 && < 1.13 default-language: Haskell2010@@ -60,11 +61,21 @@ ghc-options: -Werror +common executable+ import: library++ build-depends: witch+ ghc-options:+ -rtsopts+ -threaded++ if impl(ghc >= 8.10)+ ghc-options:+ -Wno-unused-packages+ library- import: basics+ import: library - build-depends:- , template-haskell >= 2.12.0 && < 2.19 exposed-modules: Witch Witch.From@@ -73,26 +84,20 @@ Witch.TryFrom Witch.TryFromException Witch.Utility- hs-source-dirs: src/lib+ hs-source-dirs: source/library if impl(ghc >= 9.0)- hs-source-dirs: src/ghc-9.0+ hs-source-dirs: source/ghc-9.0+ elif impl(ghc >= 8.10)+ hs-source-dirs: source/ghc-8.10 else- if impl(ghc >= 8.10)- hs-source-dirs: src/ghc-8.10- else- hs-source-dirs: src/ghc-8.8+ hs-source-dirs: source/ghc-8.8 test-suite test- import: basics+ import: executable build-depends:- , HUnit >= 1.6.2 && < 1.7- , witch- ghc-options:- -rtsopts- -threaded- -Wno-all-missed-specialisations- hs-source-dirs: src/test+ , HUnit >= 1.6.1 && < 1.7+ hs-source-dirs: source/test-suite main-is: Main.hs type: exitcode-stdio-1.0