inj 1.0 → 2.0
raw patch · 7 files changed
+590/−67 lines, 7 filesdep +basesetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: base
API changes (from Hackage documentation)
- Inj: class Inj p a
- Inj: inj :: (Inj p a, (p ~ a)) => p -> a
+ Control.Inj: ($dminj) :: (Inj p a, p ~ a) => p -> a
+ Control.Inj: class Inj p a
+ Control.Inj: inj :: Inj p a => p -> a
+ Control.Inj: instance (Control.Inj.DecideFn p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ (r -> p'), Control.Inj.Inj p' a) => Control.Inj.InjFn Control.Inj.Decision_Map p r a
+ Control.Inj: instance (Control.Inj.DecideFn p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjFn Control.Inj.Decision_Wrap p s a
+ Control.Inj: instance (Control.Inj.DecideIO p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ GHC.Types.IO p', Control.Inj.Inj p' a) => Control.Inj.InjIO Control.Inj.Decision_Map p a
+ Control.Inj: instance (Control.Inj.DecideIO p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjIO Control.Inj.Decision_Wrap p a
+ Control.Inj: instance (Control.Inj.DecideIdentity p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ GHC.Internal.Data.Functor.Identity.Identity p', Control.Inj.Inj p' a) => Control.Inj.InjIdentity Control.Inj.Decision_Map p a
+ Control.Inj: instance (Control.Inj.DecideIdentity p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjIdentity Control.Inj.Decision_Wrap p a
+ Control.Inj: instance (Control.Inj.DecideList p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ [p'], Control.Inj.Inj p' a) => Control.Inj.InjList Control.Inj.Decision_Map p a
+ Control.Inj: instance (Control.Inj.DecideList p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjList Control.Inj.Decision_Wrap p a
+ Control.Inj: instance (Control.Inj.DecideMaybe p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ GHC.Internal.Maybe.Maybe p', Control.Inj.Inj p' a) => Control.Inj.InjMaybe Control.Inj.Decision_Map p a
+ Control.Inj: instance (Control.Inj.DecideMaybe p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjMaybe Control.Inj.Decision_Wrap p a
+ Control.Inj: instance (Control.Inj.DecideNonEmpty p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ GHC.Internal.Base.NonEmpty p', Control.Inj.Inj p' a) => Control.Inj.InjNonEmpty Control.Inj.Decision_Map p a
+ Control.Inj: instance (Control.Inj.DecideNonEmpty p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjNonEmpty Control.Inj.Decision_Wrap p a
+ Control.Inj: instance (Control.Inj.DecideST p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ GHC.Internal.ST.ST s p', Control.Inj.Inj p' a) => Control.Inj.InjST Control.Inj.Decision_Map p s a
+ Control.Inj: instance (Control.Inj.DecideST p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjST Control.Inj.Decision_Wrap p s a
+ Control.Inj: instance (Control.Inj.DecideSTM p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ GHC.Internal.Conc.Sync.STM p', Control.Inj.Inj p' a) => Control.Inj.InjSTM Control.Inj.Decision_Map p a
+ Control.Inj: instance (Control.Inj.DecideSTM p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjSTM Control.Inj.Decision_Wrap p a
+ Control.Inj: instance (Control.Inj.DecideZipList p GHC.Types.~ Control.Inj.Decision_Map, p GHC.Types.~ GHC.Internal.Functor.ZipList.ZipList p', Control.Inj.Inj p' a) => Control.Inj.InjZipList Control.Inj.Decision_Map p a
+ Control.Inj: instance (Control.Inj.DecideZipList p GHC.Types.~ Control.Inj.Decision_Wrap, Control.Inj.Inj p a) => Control.Inj.InjZipList Control.Inj.Decision_Wrap p a
+ Control.Inj: instance (Data.Fixed.HasResolution res, GHC.Internal.Real.Real p) => Control.Inj.Inj p (Data.Fixed.Fixed res)
+ Control.Inj: instance (GHC.Internal.Num.Num a, Control.Inj.Inj p a) => Control.Inj.Inj p (Data.Complex.Complex a)
+ Control.Inj: instance (GHC.Internal.Real.Integral a, GHC.Internal.Real.Real p) => Control.Inj.Inj p (GHC.Internal.Real.Ratio a)
+ Control.Inj: instance (p GHC.Types.~ ()) => Control.Inj.Inj p ()
+ Control.Inj: instance (p GHC.Types.~ GHC.Internal.Data.Proxy.Proxy t') => Control.Inj.Inj p (GHC.Internal.Data.Proxy.Proxy t)
+ Control.Inj: instance (p GHC.Types.~ GHC.Types.Bool) => Control.Inj.Inj p GHC.Types.Bool
+ Control.Inj: instance (p GHC.Types.~ GHC.Types.Char) => Control.Inj.Inj p GHC.Types.Char
+ Control.Inj: instance (p GHC.Types.~ GHC.Types.Ordering) => Control.Inj.Inj p GHC.Types.Ordering
+ Control.Inj: instance (t GHC.Types.~ (pa, pb), Control.Inj.Inj pa a, Control.Inj.Inj pb b) => Control.Inj.Inj t (a, b)
+ Control.Inj: instance (t GHC.Types.~ (pa, pb, pc), Control.Inj.Inj pa a, Control.Inj.Inj pb b, Control.Inj.Inj pc c) => Control.Inj.Inj t (a, b, c)
+ Control.Inj: instance (t GHC.Types.~ (pa, pb, pc, pd), Control.Inj.Inj pa a, Control.Inj.Inj pb b, Control.Inj.Inj pc c, Control.Inj.Inj pd d) => Control.Inj.Inj t (a, b, c, d)
+ Control.Inj: instance (t GHC.Types.~ GHC.Internal.Data.Either.Either pa pb, Control.Inj.Inj pa a, Control.Inj.Inj pb b) => Control.Inj.Inj t (GHC.Internal.Data.Either.Either a b)
+ Control.Inj: instance (t GHC.Types.~ GHC.Internal.Data.Functor.Const.Const pa pb, Control.Inj.Inj pa a) => Control.Inj.Inj t (GHC.Internal.Data.Functor.Const.Const a b)
+ Control.Inj: instance Control.Inj.Inj p (f (g a)) => Control.Inj.Inj p ((GHC.Internal.Generics.:.:) f g a)
+ Control.Inj: instance Control.Inj.Inj p (f (g a)) => Control.Inj.Inj p (Data.Functor.Compose.Compose f g a)
+ Control.Inj: instance Control.Inj.Inj p (f a) => Control.Inj.Inj p (GHC.Internal.Generics.M1 i c f a)
+ Control.Inj: instance Control.Inj.Inj p (f a) => Control.Inj.Inj p (GHC.Internal.Generics.Rec1 f a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (Data.Semigroup.First a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (Data.Semigroup.Last a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (Data.Semigroup.Max a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (Data.Semigroup.Min a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Data.Monoid.First a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Data.Monoid.Last a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Data.Ord.Down a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Data.Semigroup.Internal.Dual a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Data.Semigroup.Internal.Product a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Data.Semigroup.Internal.Sum a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Generics.K1 i a x)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Generics.Par1 a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Text.ParserCombinators.ReadP.ReadP a)
+ Control.Inj: instance Control.Inj.Inj p a => Control.Inj.Inj p (GHC.Internal.Text.ParserCombinators.ReadPrec.ReadPrec a)
+ Control.Inj: instance Control.Inj.InjFn (Control.Inj.DecideFn p) p r a => Control.Inj.Inj p (r -> a)
+ Control.Inj: instance Control.Inj.InjIO (Control.Inj.DecideIO p) p a => Control.Inj.Inj p (GHC.Types.IO a)
+ Control.Inj: instance Control.Inj.InjIdentity (Control.Inj.DecideIdentity p) p a => Control.Inj.Inj p (GHC.Internal.Data.Functor.Identity.Identity a)
+ Control.Inj: instance Control.Inj.InjList (Control.Inj.DecideList p) p a => Control.Inj.Inj p [a]
+ Control.Inj: instance Control.Inj.InjMaybe (Control.Inj.DecideMaybe p) p a => Control.Inj.Inj p (GHC.Internal.Maybe.Maybe a)
+ Control.Inj: instance Control.Inj.InjNonEmpty (Control.Inj.DecideNonEmpty p) p a => Control.Inj.Inj p (GHC.Internal.Base.NonEmpty a)
+ Control.Inj: instance Control.Inj.InjST (Control.Inj.DecideST p) p s a => Control.Inj.Inj p (GHC.Internal.ST.ST s a)
+ Control.Inj: instance Control.Inj.InjSTM (Control.Inj.DecideSTM p) p a => Control.Inj.Inj p (GHC.Internal.Conc.Sync.STM a)
+ Control.Inj: instance Control.Inj.InjZipList (Control.Inj.DecideZipList p) p a => Control.Inj.Inj p (GHC.Internal.Functor.ZipList.ZipList a)
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Foreign.Ptr.IntPtr
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Foreign.Ptr.WordPtr
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Int.Int16
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Int.Int32
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Int.Int64
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Int.Int8
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Word.Word16
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Word.Word32
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Word.Word64
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Internal.Word.Word8
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Num.Integer.Integer
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Num.Natural.Natural
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Types.Int
+ Control.Inj: instance GHC.Internal.Real.Integral p => Control.Inj.Inj p GHC.Types.Word
+ Control.Inj: instance GHC.Internal.Real.Real p => Control.Inj.Inj p GHC.Types.Double
+ Control.Inj: instance GHC.Internal.Real.Real p => Control.Inj.Inj p GHC.Types.Float
Files
- CHANGELOG.md +18/−0
- Inj.hs +0/−60
- LICENSE +30/−0
- README.md +39/−0
- Setup.hs +0/−2
- inj.cabal +23/−5
- src/Control/Inj.hs +480/−0
+ CHANGELOG.md view
@@ -0,0 +1,18 @@+# Changelog++## 2.0++* Merged `inj-base` into `inj`. The instances for `base` types are no longer+ orphans and no longer require a separate package.+* Renamed the `Inj` module to `Control.Inj`. Users of `inj-1.0` should update+ their imports from `Inj` to `Control.Inj`; users of `inj-base-0.2` should+ replace `Inj.Base` with `Control.Inj`.+* Removed the instance for `Data.Semigroup.Option`, which no longer exists in+ `base`.+* Added the missing identity instance for `Char`, so that `inj 'a' :: String`+ and similar now work.+* Changed the license from `PublicDomain` to `BSD-3-Clause`.++## 1.0++* Initial release.
− Inj.hs
@@ -1,60 +0,0 @@-{- |--An injection is a function that never maps distinct elements of the domain to-the same element of the codomain. For example, @(\\x -> x + 1)@ is an injection,-but @(\\x -> min x 0)@ is not.--Injections can be used to construct nested structures from singleton elements.---}--{-# LANGUAGE NoImplicitPrelude,- DefaultSignatures,- MultiParamTypeClasses,- TypeFamilies #-}--module Inj (Inj(..)) where---- | Inject @p@ into @a@.------ By convention, the instances of @Inj@ never match on @p@ and always match on--- @a@. This guarantees that the users will not encounter overlapping instances.-class Inj p a where- -- | Inject @p@ into @a@.- inj :: p -> a-- default inj :: (p ~ a) => p -> a- inj = \x -> x---- @instance Inj a a@ is tempting to define. Unfortunately, it does not work--- as well as one might hope. For instance, consider a type like this:------ @--- data Shape x = Circle | Rectangle | Other x--- deriving Functor--- @------ If we want to write @inj Circle@, then we get an ambiguity error:------ @--- * Could not deduce (Inj (Shape x0) (Shape x))--- arising from a use of `inj'--- @------ That is because @Inj a a@ for @Shape x@ is equivalent to------ @instance Inj (Shape x) (Shape x)@------ but for good type inference we want------ @instance (x1 ~ x2) => Inj (Shape x1) (Shape x2)@------ Furthermore, we can take advantage of @Shape@ being a functor and--- define an even better instance:------ @--- instance Inj a b => Inj (Shape a) (Shape b) where--- inj = fmap inj--- @------ Unfortunately, both of the better instances are overlapping with @Inj a a@.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2018, Vladislav Zavialov++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Vladislav Zavialov nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,39 @@+# inj++A class for injective (one-to-one) functions.++An injection is a function that never maps distinct elements of the domain to+the same element of the codomain. For example, `\x -> x + 1` is an injection,+but `\x -> min x 0` is not.++```haskell+class Inj p a where+ inj :: p -> a+```++The instances compose, so `inj` can construct nested structures from singleton+elements, wrapping and converting as needed:++```haskell+ghci> inj 'a' :: Maybe [Char]+Just "a"++ghci> inj True :: Maybe [Bool]+Just [True]++ghci> inj (5 :: Int) :: Maybe Double+Just 5.0++ghci> inj [1, 2, 3 :: Int] :: [Double]+[1.0,2.0,3.0]++ghci> inj (True, 2 :: Int) :: (Maybe Bool, [Double])+(Just True,[2.0])+```++By convention, the instances of `Inj` never match on `p` and always match on+`a`. This guarantees that users will not encounter overlapping instances.++Instances for `base` types are provided by this package. Before version 2.0+they lived in a separate `inj-base` package; see the [changelog](CHANGELOG.md)+for migration notes.
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
inj.cabal view
@@ -1,14 +1,32 @@+cabal-version: 3.0 name: inj-version: 1.0+version: 2.0 synopsis: A class for injective (one-to-one) functions-license: PublicDomain+description:+ An injection is a function that never maps distinct elements of the domain+ to the same element of the codomain. For example, @(\\x -> x + 1)@ is an+ injection, but @(\\x -> min x 0)@ is not.+ .+ This package provides the @Inj@ class, whose instances can be composed to+ construct nested structures from singleton elements.+license: BSD-3-Clause+license-file: LICENSE author: Vladislav Zavialov maintainer: Vladislav Zavialov <vlad.z.4096@gmail.com>-category: Data+category: Control build-type: Simple-cabal-version: >=1.10+tested-with: GHC ==9.2.8, GHC ==9.4.8, GHC ==9.6.7, GHC ==9.8.4,+ GHC ==9.10.3, GHC ==9.12.4, GHC ==9.14.1+extra-doc-files: README.md+ CHANGELOG.md +source-repository head+ type: git+ location: https://github.com/int-index/inj.git+ library- exposed-modules: Inj+ exposed-modules: Control.Inj+ build-depends: base >=4.16 && <5+ hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall
+ src/Control/Inj.hs view
@@ -0,0 +1,480 @@+{- |++An injection is a function that never maps distinct elements of the domain to+the same element of the codomain. For example, @(\\x -> x + 1)@ is an injection,+but @(\\x -> min x 0)@ is not.++Injections can be used to construct nested structures from singleton elements.++-}++{-# LANGUAGE DefaultSignatures,+ FlexibleContexts,+ FlexibleInstances,+ MultiParamTypeClasses,+ ScopedTypeVariables,+ TypeFamilies,+ TypeOperators,+ UndecidableInstances+#-}++module Control.Inj (Inj(..)) where++import Control.Applicative+import Control.Exception hiding (TypeError)+import Control.Monad.ST+import Data.Bifunctor+import Data.Complex+import Data.Fixed+import Data.Functor.Compose+import Data.Functor.Identity+import Data.Int+import Data.List.NonEmpty+import Data.Monoid+import Data.Ord+import Data.Proxy+import Data.Ratio+import Data.Semigroup+import Data.Word+import Foreign.Ptr+import GHC.Conc+import GHC.Generics+import Numeric.Natural+import Text.ParserCombinators.ReadP+import Text.ParserCombinators.ReadPrec++-- | Inject @p@ into @a@.+--+-- By convention, the instances of @Inj@ never match on @p@ and always match on+-- @a@. This guarantees that the users will not encounter overlapping instances.+class Inj p a where+ -- | Inject @p@ into @a@.+ inj :: p -> a++ default inj :: (p ~ a) => p -> a+ inj = \x -> x++-- @instance Inj a a@ is tempting to define. Unfortunately, it does not work+-- as well as one might hope. For instance, consider a type like this:+--+-- @+-- data Shape x = Circle | Rectangle | Other x+-- @+--+-- If we want to write @inj Circle@, then we get an ambiguity error:+--+-- @+-- * Could not deduce (Inj (Shape x0) (Shape x))+-- arising from a use of `inj'+-- @+--+-- That is because @Inj a a@ for @Shape x@ is equivalent to+--+-- @instance Inj (Shape x) (Shape x)@+--+-- but for good type inference we want+--+-- @instance (p ~ Shape x) => Inj p (Shape x)@+--+-- Unfortunately, this instance can't be used in the presence of @Inj a a@+-- due to overlap.++--------------------------------------------------------------------------------+-- Identity injections+--------------------------------------------------------------------------------++instance p ~ () => Inj p ()+instance p ~ Bool => Inj p Bool+instance p ~ Char => Inj p Char+instance p ~ Ordering => Inj p Ordering++instance p ~ Proxy t' => Inj p (Proxy t) where+ inj Proxy = Proxy++--------------------------------------------------------------------------------+-- Decision procedures for ambiguous injections+--------------------------------------------------------------------------------++data Decision_Wrap++data Decision_Map++type family DecideMaybe p where+ DecideMaybe (Maybe p) = Decision_Map+ DecideMaybe p = Decision_Wrap++class d ~ DecideMaybe p => InjMaybe d p a where+ injMaybe :: p -> Maybe a++instance InjMaybe (DecideMaybe p) p a => Inj p (Maybe a) where+ inj = injMaybe++type family DecideList p where+ DecideList [p] = Decision_Map+ DecideList p = Decision_Wrap++class d ~ DecideList p => InjList d p a where+ injList :: p -> [a]++instance InjList (DecideList p) p a => Inj p [a] where+ inj = injList++type family DecideNonEmpty p where+ DecideNonEmpty (NonEmpty p) = Decision_Map+ DecideNonEmpty p = Decision_Wrap++class d ~ DecideNonEmpty p => InjNonEmpty d p a where+ injNonEmpty :: p -> NonEmpty a++instance InjNonEmpty (DecideNonEmpty p) p a => Inj p (NonEmpty a) where+ inj = injNonEmpty++type family DecideIO p where+ DecideIO (IO p) = Decision_Map+ DecideIO p = Decision_Wrap++class d ~ DecideIO p => InjIO d p a where+ injIO :: p -> IO a++instance InjIO (DecideIO p) p a => Inj p (IO a) where+ inj = injIO++type family DecideSTM p where+ DecideSTM (STM p) = Decision_Map+ DecideSTM p = Decision_Wrap++class d ~ DecideSTM p => InjSTM d p a where+ injSTM :: p -> STM a++instance InjSTM (DecideSTM p) p a => Inj p (STM a) where+ inj = injSTM++type family DecideIdentity p where+ DecideIdentity (Identity p) = Decision_Map+ DecideIdentity p = Decision_Wrap++class d ~ DecideIdentity p => InjIdentity d p a where+ injIdentity :: p -> Identity a++instance InjIdentity (DecideIdentity p) p a => Inj p (Identity a) where+ inj = injIdentity++type family DecideZipList p where+ DecideZipList (ZipList p) = Decision_Map+ DecideZipList p = Decision_Wrap++class d ~ DecideZipList p => InjZipList d p a where+ injZipList :: p -> ZipList a++instance InjZipList (DecideZipList p) p a => Inj p (ZipList a) where+ inj = injZipList++type family DecideST p where+ DecideST (ST s p) = Decision_Map+ DecideST p = Decision_Wrap++class d ~ DecideST p => InjST d p s a where+ injST :: p -> ST s a++instance InjST (DecideST p) p s a => Inj p (ST s a) where+ inj = injST++type family DecideFn p where+ DecideFn (r -> p) = Decision_Map+ DecideFn p = Decision_Wrap++class d ~ DecideFn p => InjFn d p r a where+ injFn :: p -> r -> a++instance InjFn (DecideFn p) p r a => Inj p (r -> a) where+ inj = injFn++--------------------------------------------------------------------------------+-- 'fromIntegral' is an injection from any @Integral p@ to any @Num a@.+--------------------------------------------------------------------------------++instance Integral p => Inj p Integer where+ inj = toInteger++-- | Throws 'Underflow'.+instance Integral p => Inj p Natural where+ inj = fromIntegral++fromIntegralBounded ::+ forall p a. (Integral a, Bounded a) => Integral p => p -> a+fromIntegralBounded p+ | p' < toInteger (minBound :: a) = throw Underflow+ | p' > toInteger (maxBound :: a) = throw Overflow+ | otherwise = fromInteger p'+ where+ p' = toInteger p++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Int where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Int8 where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Int16 where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Int32 where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Int64 where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Word where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Word8 where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Word16 where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Word32 where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p Word64 where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p IntPtr where+ inj = fromIntegralBounded++-- | Throws 'Underflow' and 'Overflow'.+instance Integral p => Inj p WordPtr where+ inj = fromIntegralBounded++--------------------------------------------------------------------------------+-- 'realToFrac' is an injection from any @Real p@ to any @Fractional a@.+--------------------------------------------------------------------------------++instance (Integral a, Real p) => Inj p (Ratio a) where+ inj = realToFrac++-- | Throws 'LossOfPrecision'.+instance (HasResolution res, Real p) => Inj p (Fixed res) where+ inj p+ | denominator i == 1 = MkFixed (numerator i)+ | otherwise = throw LossOfPrecision+ where+ i = toRational p * toRational res+ res = resolution (Proxy :: Proxy res)++-- | Injective only if the number is representable as 'Float'.+instance Real p => Inj p Float where+ inj = realToFrac++-- | Injective only if the number is representable as 'Double'.+instance Real p => Inj p Double where+ inj = realToFrac++instance (Num a, Inj p a) => Inj p (Complex a) where+ inj p = inj p :+ 0++--------------------------------------------------------------------------------+-- 'pure' is often an injection into @Applicative f@.+--------------------------------------------------------------------------------++instance+ (DecideList p ~ Decision_Wrap, Inj p a) =>+ InjList Decision_Wrap p a+ where+ injList = pure . inj++instance+ (DecideMaybe p ~ Decision_Wrap, Inj p a) =>+ InjMaybe Decision_Wrap p a+ where+ injMaybe = pure . inj++instance+ (DecideNonEmpty p ~ Decision_Wrap, Inj p a) =>+ InjNonEmpty Decision_Wrap p a+ where+ injNonEmpty = pure . inj++instance+ (DecideIO p ~ Decision_Wrap, Inj p a) =>+ InjIO Decision_Wrap p a+ where+ injIO = pure . inj++instance Inj p a => Inj p (ReadP a) where+ inj = pure . inj++instance Inj p a => Inj p (ReadPrec a) where+ inj = pure . inj++instance Inj p a => Inj p (Down a) where+ inj = pure . inj++instance Inj p a => Inj p (Product a) where+ inj = pure . inj++instance Inj p a => Inj p (Sum a) where+ inj = pure . inj++instance Inj p a => Inj p (Dual a) where+ inj = pure . inj++instance Inj p a => Inj p (Data.Monoid.Last a) where+ inj = pure . inj++instance Inj p a => Inj p (Data.Monoid.First a) where+ inj = pure . inj++instance+ (DecideSTM p ~ Decision_Wrap, Inj p a) =>+ InjSTM Decision_Wrap p a+ where+ injSTM = pure . inj++instance+ (DecideIdentity p ~ Decision_Wrap, Inj p a) =>+ InjIdentity Decision_Wrap p a+ where+ injIdentity = pure . inj++instance+ (DecideZipList p ~ Decision_Wrap, Inj p a) =>+ InjZipList Decision_Wrap p a+ where+ injZipList = pure . inj++instance Inj p a => Inj p (Data.Semigroup.Last a) where+ inj = pure . inj++instance Inj p a => Inj p (Data.Semigroup.First a) where+ inj = pure . inj++instance Inj p a => Inj p (Max a) where+ inj = pure . inj++instance Inj p a => Inj p (Min a) where+ inj = pure . inj++instance+ (DecideST p ~ Decision_Wrap, Inj p a) =>+ InjST Decision_Wrap p s a+ where+ injST = pure . inj++instance+ (DecideFn p ~ Decision_Wrap, Inj p a) =>+ InjFn Decision_Wrap p s a+ where+ injFn = pure . inj++instance Inj p (f (g a)) => Inj p (Compose f g a) where+ inj = Compose . inj++--------------------------------------------------------------------------------+-- 'fmap', 'bimap', etc, can be used to map injections+--------------------------------------------------------------------------------++instance+ (DecideMaybe p ~ Decision_Map, p ~ Maybe p', Inj p' a) =>+ InjMaybe Decision_Map p a+ where+ injMaybe = fmap inj++instance+ (DecideList p ~ Decision_Map, p ~ [p'], Inj p' a) =>+ InjList Decision_Map p a+ where+ injList = fmap inj++instance+ (DecideNonEmpty p ~ Decision_Map, p ~ NonEmpty p', Inj p' a) =>+ InjNonEmpty Decision_Map p a+ where+ injNonEmpty = fmap inj++instance+ (DecideIO p ~ Decision_Map, p ~ IO p', Inj p' a) =>+ InjIO Decision_Map p a+ where+ injIO = fmap inj++instance+ (DecideSTM p ~ Decision_Map, p ~ STM p', Inj p' a) =>+ InjSTM Decision_Map p a+ where+ injSTM = fmap inj++instance+ (DecideIdentity p ~ Decision_Map, p ~ Identity p', Inj p' a) =>+ InjIdentity Decision_Map p a+ where+ injIdentity = fmap inj++instance+ (DecideZipList p ~ Decision_Map, p ~ ZipList p', Inj p' a) =>+ InjZipList Decision_Map p a+ where+ injZipList = fmap inj++instance+ (DecideST p ~ Decision_Map, p ~ ST s p', Inj p' a) =>+ InjST Decision_Map p s a+ where+ injST = fmap inj++instance+ (DecideFn p ~ Decision_Map, p ~ (r -> p'), Inj p' a) =>+ InjFn Decision_Map p r a+ where+ injFn = fmap inj++instance (t ~ (pa, pb), Inj pa a, Inj pb b) => Inj t (a, b) where+ inj = bimap inj inj++instance+ (t ~ (pa, pb, pc), Inj pa a, Inj pb b, Inj pc c) =>+ Inj t (a, b, c)+ where+ inj (pa, pb, pc) = (inj pa, inj pb, inj pc)++instance+ (t ~ (pa, pb, pc, pd), Inj pa a, Inj pb b, Inj pc c, Inj pd d) =>+ Inj t (a, b, c, d)+ where+ inj (pa, pb, pc, pd) = (inj pa, inj pb, inj pc, inj pd)++instance (t ~ Either pa pb, Inj pa a, Inj pb b) => Inj t (Either a b) where+ inj = bimap inj inj++instance (t ~ Const pa pb, Inj pa a) => Inj t (Const a b) where+ inj (Const pa) = Const (inj pa)++--------------------------------------------------------------------------------+-- Generic+--------------------------------------------------------------------------------++instance Inj p (f a) => Inj p (Rec1 f a) where+ inj = Rec1 . inj++instance Inj p (f a) => Inj p (M1 i c f a) where+ inj = M1 . inj++instance Inj p a => Inj p (Par1 a) where+ inj = Par1 . inj++instance Inj p a => Inj p (K1 i a x) where+ inj = K1 . inj++instance Inj p (f (g a)) => Inj p ((:.:) f g a) where+ inj = Comp1 . inj