{-# LANGUAGE RankNTypes, DeriveAnyClass, TypeOperators #-} module Enumerate.Function.Types where import Enumerate.Types import Enumerate.Function.Extra import Control.Monad.Catch (MonadThrow) import Control.DeepSeq import Data.Ix (Ix) {-| see "Enumerate.Function.Reify.getJectivityM" -} data Jectivity = Injective | Surjective | Bijective deriving (Show,Read,Eq,Ord,Enum,Bounded,Ix,Generic,Data ,NFData,Enumerable) {- with proof: the signature of the inverse of (a -> b) data Jectivity a b = Unjective (b -> [a]) | Injective (b -> Maybe a) | Surjective (b -> NonEmpty a) | Bijective (b -> a) data Jectivity_ = Injective_ | Surjective_ | Bijective_ jectivity :: () => (a -> b) -> Jectivity a b jectivity_ :: Jectivity -> Maybe Jectivity_ OR newtype Injection a b = Injection (a -> b) (b -> Maybe a) newtype Surjection a b = Surjection (a -> b) (b -> NonEmpty a) newtype Bijection a b = Bijection (a -> b) (b -> a) -- | each input has zero-or-one output newtype a :?->: b = Injection (a -> b) (b -> Maybe a) -- | each input has one-or-more output newtype a :+->: b = Surjection (a -> b) (b -> NonEmpty a) -- | each input has one output newtype a :<->: b = Bijection (a -> b) (b -> a) toInjection :: (a -> b) -> Maybe (Injection a b) toSurjection :: (a -> b) -> Maybe (Surjection a b) toBijection :: (a -> b) -> Maybe (Bijection a b) asInjection :: (a :<->: b) -> (a :?->: b) asInjection (Bijection f g) = Injection f (Just <$> g) -- pure asSurjection :: (a :<->: b) -> (a :+->: b) asSurjection (Bijection f g) = Surjection f ((:|[]) <$> g) -- pure -} {-| a (safely-)partial function. i.e. a function that: * fails only via the 'throwM' method of 'MonadThrow' * succeeds only via the 'return' method of 'Monad' -} type Partial a b = (forall m. MonadThrow m => a -> m b) type (a -?> b) = Partial a b -------------------------------------------------------------------------------- -- (by necessity) @'KnownNat' ('Cardinality' a)@ --class (KnownNat (Cardinality a)) => Enumerable a where -- type Cardinality a :: Nat -- TODO {- too much boilerplate e.g. instance Enumerable Jectivity errors with: No instance for (KnownNat (Cardinality Jectivity)) arising from the superclasses of an instance declaration In the instance declaration for `Enumerable Jectivity' would need: instance (KnownNat (Cardinality Jectivity)) => Enumerable Jectivity -}