{-# LANGUAGE TypeFamilies, ConstraintKinds, FlexibleInstances, MultiParamTypeClasses #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | Existential datatypes holding evidence of constraints, and type classes for existential datatypes. module Data.Exists (module Data.Exists.Internal) where import Data.Exists.Internal import Data.Exists.Defaults import Prelude ((.), error) import Unsafe.Coerce (unsafeCoerce) import qualified Data.Traversable as T (foldMapDefault, fmapDefault) import Data.Dynamic (toDyn, fromDyn) --import Control.Comonad (liftW) import Control.Constraint.Combine (Empty) import Data.Typeable (Typeable) import Control.Exception (Exception) import Data.Dynamic (Dynamic) import GHC.Exts (Any) import Data.Anything (Anything (..), Anything1 (..)) import Control.Exception (SomeException (..)) import Prelude (Show (..), Functor (..)) import Data.Foldable (Foldable (..)) import Data.Traversable (Traversable (..)) import Data.Functor.Contravariant (Contravariant (..)) {- import Data.Functor.Extend (Extend (..)) import Control.Comonad (Comonad (..)) import Control.Comonad.Env.Class (ComonadEnv (..)) import Control.Comonad.Traced.Class (ComonadTraced (..)) import Control.Comonad.Store.Class (ComonadStore (..)) import Data.Copointed (Copointed (..)) -} -- | @'ConstraintOf' 'Any' = 'Empty'@ instance Existential Any where type ConstraintOf Any = Empty exists = unsafeCoerce apply f a = f a -- this is OK, because f by its type signature must be completely parametric -- with respect to a -- | @'ConstraintOf1' 'Any' = 'Empty'@ instance Existential1 Any where type ConstraintOf1 Any = Empty exists1 = unsafeCoerce apply1 f a = f a -- likewise -- | @'ConstraintOf' 'Anything' = 'Empty'@ instance Existential Anything where type ConstraintOf Anything = Empty exists = Anything apply f (Anything a) = f a -- | @'ConstraintOf1' 'Anything1' = 'Empty'@ instance Existential1 Anything1 where type ConstraintOf1 Anything1 = Empty exists1 = Anything1 apply1 f (Anything1 a) = f a -- | @'ConstraintOf' 'Dynamic' = 'Typeable'@ instance Existential Dynamic where type ConstraintOf Dynamic = Typeable exists = toDyn apply f d = f (fromDyn (error "this can't be happening!") d) -- if I'm thinking correctly, nothing bad can result from this, because: -- - f can only use what Typeable provides; -- - typeOf is required to work on bottom values; -- - if f tries to cast its argument to the type which was in the Dynamic, -- the argument will be the value from the Dynamic and won't be bottom; -- - if f tries to cast its argument to a different type, the argument will -- be bottom, but Typeable won't allow the cast to succeed and it won't -- matter. -- | @'ConstraintOf' 'SomeException' = 'Exception'@ instance Existential SomeException where type ConstraintOf SomeException = Exception exists = SomeException apply f (SomeException e) = f e -- instance Show (Exists Exception) where -- show = apply show -- instance Exception (Exists Exception) where -- fromException = fromExceptionDefault -- toException = toExceptionDefault -- -- this unfortunately can't work, because Exception requires Typeable as a -- superclass, Typeable only has typeOf as its method, and Typeable.cast will -- indiscriminately unsafeCoerce based on the result of typeOf: so even if we -- pass through the typeOf the underlying type, we're screwed because -- Exists Exception is not physically that type. If we were to use the typeOf -- (Exists Exception), we'd still be screwed from the other direction, but we -- can't do that because Typeable isn't available for Constraints. instance Show (Exists Show) where show = showDefault showsPrec = showsPrecDefault instance Functor (Exists1 Functor) where fmap = fmapDefault instance Foldable (Exists1 Foldable) where fold = foldDefault foldMap = foldMapDefault foldl = foldlDefault foldr = foldrDefault foldl1 = foldl1Default foldr1 = foldr1Default instance Functor (Exists1 Traversable) where fmap = T.fmapDefault instance Foldable (Exists1 Traversable) where foldMap = T.foldMapDefault instance Traversable (Exists1 Traversable) where traverse = traverseDefault sequenceA = sequenceADefault mapM = mapMDefault sequence = sequenceDefault instance Contravariant (Exists1 Contravariant) where contramap = contramapDefault {- instance Functor (Exists1 Extend) where fmap f = apply1 (exists1 . fmap f) instance Extend (Exists1 Extend) where duplicate = duplicateDefault instance Functor (Exists1 Comonad) where fmap = liftW instance Extend (Exists1 Comonad) where duplicate = apply1 (exists1 . fmap exists1 . duplicate) instance Comonad (Exists1 Comonad) where extract = extractDefault instance Functor (Exists1 (ComonadEnv e)) where fmap = liftW instance Extend (Exists1 (ComonadEnv e)) where duplicate = apply1 (exists1 . fmap exists1 . duplicate) instance Comonad (Exists1 (ComonadEnv e)) where extract = apply1 extract instance ComonadEnv e (Exists1 (ComonadEnv e)) where ask = askDefault instance Functor (Exists1 (ComonadTraced m)) where fmap = liftW instance Extend (Exists1 (ComonadTraced m)) where duplicate = apply1 (exists1 . fmap exists1 . duplicate) instance Comonad (Exists1 (ComonadTraced m)) where extract = apply1 extract instance ComonadTraced m (Exists1 (ComonadTraced m)) where trace = traceDefault instance Functor (Exists1 (ComonadStore s)) where fmap = liftW instance Extend (Exists1 (ComonadStore s)) where duplicate = apply1 (exists1 . fmap exists1 . duplicate) instance Comonad (Exists1 (ComonadStore s)) where extract = apply1 extract instance ComonadStore s (Exists1 (ComonadStore s)) where pos = posDefault peek = peekDefault peeks = peeksDefault seek = seekDefault seeks = seeksDefault instance Copointed (Exists1 Copointed) where copoint = copointDefault -}