-- | -- Module : Data.Functor.Combinator.Unsafe -- Copyright : (c) Justin Le 2019 -- License : BSD3 -- -- Maintainer : justin@jle.im -- Stability : experimental -- Portability : non-portable -- -- Working with non-standard typeclasses like 'Plus', 'Apply', 'Bind', and -- 'Pointed' will sometimes cause problems when using with libraries that -- do not provide instances, even though their types already are instances -- of 'Alternative' or 'Applicative' or 'Monad'. -- -- This module provides unsafe methods to "promote" 'Applicative' instances -- to 'Apply', 'Alternative' to 'Plus', etc. -- -- They are unsafe in the sense that if those types /already/ have those -- instances, this will cause overlapping instances errors or problems with -- coherence. Because of this, you should always use these with /specific/ -- @f@s, and never in a polymorphic way over @f@. module Data.Functor.Combinator.Unsafe ( unsafePlus , unsafeApply , unsafeBind , unsafePointed , unsafeConclude , unsafeDivise ) where import Control.Applicative import Data.Constraint import Data.Constraint.Unsafe import Data.Functor.Bind import Data.Functor.Contravariant.Conclude import Data.Functor.Contravariant.Divise import Data.Functor.Contravariant.Divisible import Data.Functor.Plus import Data.Pointed -- | For any @'Alternative' f@, produce a value that would require @'Plus' -- f@. -- -- Always use with concrete and specific @f@ only, and never use with any -- @f@ that already has a 'Plus' instance. -- -- See documentation for 'Data.HBifunctor.Tensor.upgradeC' for example -- usages. -- -- The 'Data.Proxy.Proxy' argument allows you to specify which specific @f@ -- you want to enhance. You can pass in something like @'Data.Proxy.Proxy' -- \@MyFunctor@. unsafePlus :: forall f proxy r. Alternative f => proxy f -> (Plus f => r) -> r unsafePlus :: proxy f -> (Plus f => r) -> r unsafePlus _ x :: Plus f => r x = case Plus (WrappedApplicative f) :- Plus f forall (a :: Constraint) (b :: Constraint). a :- b unsafeCoerceConstraint @(Plus (WrappedApplicative f)) @(Plus f) of Sub Dict -> r Plus f => r x -- | For any @'Applicative' f@, produce a value that would require @'Apply' -- f@. -- -- Always use with concrete and specific @f@ only, and never use with any -- @f@ that already has a 'Apply' instance. -- -- See documentation for 'Data.HBifunctor.Tensor.upgradeC' for example -- usages. -- -- The 'Data.Proxy.Proxy' argument allows you to specify which specific @f@ -- you want to enhance. You can pass in something like @'Data.Proxy.Proxy' -- \@MyFunctor@. unsafeApply :: forall f proxy r. Applicative f => proxy f -> (Apply f => r) -> r unsafeApply :: proxy f -> (Apply f => r) -> r unsafeApply _ x :: Apply f => r x = case Apply (WrappedApplicative f) :- Apply f forall (a :: Constraint) (b :: Constraint). a :- b unsafeCoerceConstraint @(Apply (WrappedApplicative f)) @(Apply f) of Sub Dict -> r Apply f => r x -- | For any @'Monad' f@, produce a value that would require @'Bind' -- f@. -- -- Always use with concrete and specific @f@ only, and never use with any -- @f@ that already has a 'Bind' instance. -- -- See documentation for 'Data.HBifunctor.Tensor.upgradeC' for example -- usages. -- -- The 'Data.Proxy.Proxy' argument allows you to specify which specific @f@ -- you want to enhance. You can pass in something like @'Data.Proxy.Proxy' -- \@MyFunctor@. unsafeBind :: forall f proxy r. Monad f => proxy f -> (Bind f => r) -> r unsafeBind :: proxy f -> (Bind f => r) -> r unsafeBind _ x :: Bind f => r x = case Bind (WrappedMonad f) :- Bind f forall (a :: Constraint) (b :: Constraint). a :- b unsafeCoerceConstraint @(Bind (WrappedMonad f)) @(Bind f) of Sub Dict -> r Bind f => r x newtype PointMe f a = PointMe (f a) instance Applicative f => Pointed (PointMe f) where point :: a -> PointMe f a point = f a -> PointMe f a forall k (f :: k -> *) (a :: k). f a -> PointMe f a PointMe (f a -> PointMe f a) -> (a -> f a) -> a -> PointMe f a forall b c a. (b -> c) -> (a -> b) -> a -> c . a -> f a forall (f :: * -> *) a. Applicative f => a -> f a pure -- | For any @'Applicative' f@, produce a value that would require -- @'Pointed' f@. -- -- Always use with concrete and specific @f@ only, and never use with any -- @f@ that already has a 'Pointed' instance. -- -- See documentation for 'Data.HBifunctor.Tensor.upgradeC' for example -- usages. -- -- The 'Data.Proxy.Proxy' argument allows you to specify which specific @f@ -- you want to enhance. You can pass in something like @'Data.Proxy.Proxy' -- \@MyFunctor@. unsafePointed :: forall f proxy r. Applicative f => proxy f -> (Pointed f => r) -> r unsafePointed :: proxy f -> (Pointed f => r) -> r unsafePointed _ x :: Pointed f => r x = case Pointed (PointMe f) :- Pointed f forall (a :: Constraint) (b :: Constraint). a :- b unsafeCoerceConstraint @(Pointed (PointMe f)) @(Pointed f) of Sub Dict -> r Pointed f => r x -- | For any @'Decidable' f@, produce a value that would require @'Conclude' -- f@. -- -- Always use with concrete and specific @f@ only, and never use with any -- @f@ that already has a 'Conclude' instance. -- -- See documentation for 'Data.HBifunctor.Tensor.upgradeC' for example -- usages. -- -- The 'Data.Proxy.Proxy' argument allows you to specify which specific @f@ -- you want to enhance. You can pass in something like @'Data.Proxy.Proxy' -- \@MyFunctor@. -- -- @since 0.3.0.0 unsafeConclude :: forall f proxy r. Decidable f => proxy f -> (Conclude f => r) -> r unsafeConclude :: proxy f -> (Conclude f => r) -> r unsafeConclude _ x :: Conclude f => r x = case Conclude (WrappedDivisible f) :- Conclude f forall (a :: Constraint) (b :: Constraint). a :- b unsafeCoerceConstraint @(Conclude (WrappedDivisible f)) @(Conclude f) of Sub Dict -> r Conclude f => r x -- | For any @'Divisible' f@, produce a value that would require @'Divise' -- f@. -- -- Always use with concrete and specific @f@ only, and never use with any -- @f@ that already has a 'Divise' instance. -- -- See documentation for 'Data.HBifunctor.Tensor.upgradeC' for example -- usages. -- -- The 'Data.Proxy.Proxy' argument allows you to specify which specific @f@ -- you want to enhance. You can pass in something like @'Data.Proxy.Proxy' -- \@MyFunctor@. -- -- @since 0.3.0.0 unsafeDivise :: forall f proxy r. Divisible f => proxy f -> (Divise f => r) -> r unsafeDivise :: proxy f -> (Divise f => r) -> r unsafeDivise _ x :: Divise f => r x = case Divise (WrappedDivisible f) :- Divise f forall (a :: Constraint) (b :: Constraint). a :- b unsafeCoerceConstraint @(Divise (WrappedDivisible f)) @(Divise f) of Sub Dict -> r Divise f => r x