{-# LANGUAGE GADTs #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} module Data.IFunctor where import Data.Data import Data.Kind {- | Singletons are not used here. I am not sure if singletons can generate the instances I need. Here is an example: Ping-Pong @ data PingPong = S0 [Bool] | S1 | S2 [Bool] | End data SPingPong :: PingPong -> Type where SS0 :: SPingPong (S0 b) SS1 :: SPingPong S1 SS2 :: SPingPong (S2 b) SEnd :: SPingPong End @ Note here /SS0 :: SPingPong (S0 b)/ Using singletons will generate /SS0 :: Sing b -> SPingPong (S0 b)/ which is not what I need. Please note the following example: @ serverPeer :: (Monad m) => Peer Role PingPong Server m (At () (Done Server)) (S0 s) serverPeer = I.do -- The server is in a state (S0 s) while it is awaiting a message, -- and its state is indeterminate until it receives a message. -- SS0 :: SPingPong (S0 b) correctly indicates this indeterminacy. Recv msg <- await case msg of Ping -> I.do yield Pong serverPeer Stop -> returnAt () @ -} type family Sing :: k -> Type type SingI :: forall {k}. k -> Constraint {- | example:Ping-Pong @ type instance Sing = SPingPong instance SingI (S0 b) where sing = SS0 instance SingI S1 where sing = SS1 instance SingI (S2 b) where sing = SS2 instance SingI End where sing = SEnd @ -} class SingI a where sing :: Sing a infixr 0 ~> type f ~> g = forall x. f x -> g x class IFunctor f where imap :: (a ~> b) -> f a ~> f b {- | McBride Indexed Monads Here's Edward Kmett's [introduction to Indexed Monads](https://stackoverflow.com/questions/28690448/what-is-indexed-monad). As he said, there are at least three indexed monads: * Bob Atkey @ class IMonad m where ireturn :: a -> m i i a ibind :: m i j a -> (a -> m j k b) -> m i k b @ * Conor McBride @ type a ~> b = forall i. a i -> b i class IMonad m where ireturn :: a ~> m a ibind :: (a ~> m b) -> (m a ~> m b) @ * Dominic Orchard No detailed description, just a link to this [lecture](https://github.com/dorchard/effect-monad/blob/master/docs/ixmonad-fita14.pdf)。 I use the McBride Indexed Monad, the earliest paper [here](https://personal.cis.strath.ac.uk/conor.mcbride/Kleisli.pdf). The following is my understanding of (\~>): through GADT, let the value contain type information, and then use ((\~>), pattern match) to pass the type to subsequent functions @ data V = A | B data SV :: V -> Type where -- GADT, let the value contain type information SA :: SV A SB :: SV B data SV1 :: V -> Type where SA1 :: SV1 A SB1 :: SV1 B fun :: SV ~> SV1 -- type f ~> g = forall x. f x -> g x fun sv = case sv of -- x is arbitrary but f, g must have the same x SA -> SA1 -- Pass concrete type state to subsequent functions via pattern matching SB -> SB1 class (IFunctor m) => IMonad m where ireturn :: a ~> m a ibind :: (a ~> m b) -- The type information contained in a will be passed to (m b), -- which is exactly what we need: external input has an impact on the type! -> m a ~> m b @ -} class (IFunctor m) => IMonad m where ireturn :: a ~> m a ibind :: (a ~> m b) -> m a ~> m b class (IMonad m) => IMonadFail m where fail :: String -> m a ix data At :: Type -> k -> k -> Type where At :: a -> At a k k deriving (Typeable) (>>=) :: (IMonad (m :: (x -> Type) -> x -> Type)) => m a ix -> (a ~> m b) -> m b ix m a ix m >>= :: forall x (m :: (x -> *) -> x -> *) (a :: x -> *) (ix :: x) (b :: x -> *). IMonad m => m a ix -> (a ~> m b) -> m b ix >>= a ~> m b f = (a ~> m b) -> m a ~> m b forall {k} (m :: (k -> *) -> k -> *) (a :: k -> *) (b :: k -> *). IMonad m => (a ~> m b) -> m a ~> m b forall (a :: x -> *) (b :: x -> *). (a ~> m b) -> m a ~> m b ibind a x -> m b x a ~> m b f m a ix m (>>) :: (IMonad (m :: (x -> Type) -> x -> Type)) => m (At a j) i -> m b j -> m b i m (At a j) i m >> :: forall x (m :: (x -> *) -> x -> *) a (j :: x) (i :: x) (b :: x -> *). IMonad m => m (At a j) i -> m b j -> m b i >> m b j f = (At a j ~> m b) -> m (At a j) ~> m b forall {k} (m :: (k -> *) -> k -> *) (a :: k -> *) (b :: k -> *). IMonad m => (a ~> m b) -> m a ~> m b forall (a :: x -> *) (b :: x -> *). (a ~> m b) -> m a ~> m b ibind (\(At a _) -> m b j m b x f) m (At a j) i m returnAt :: (IMonad m) => a -> m (At a k) k returnAt :: forall {k} (m :: (k -> *) -> k -> *) a (k :: k). IMonad m => a -> m (At a k) k returnAt = At a k k -> m (At a k) k forall {k} (m :: (k -> *) -> k -> *) (a :: k -> *). IMonad m => a ~> m a forall (a :: k -> *). a ~> m a ireturn (At a k k -> m (At a k) k) -> (a -> At a k k) -> a -> m (At a k) k forall b c a. (b -> c) -> (a -> b) -> a -> c . a -> At a k k forall {k} a (k :: k). a -> At a k k At