{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ViewPatterns #-}
module Network.TypedProtocol.Pipelined
( PeerPipelined (..)
, PeerSender (..)
, PeerReceiver (..)
, Outstanding
, N (..)
, Nat (Zero, Succ)
, natToInt
, unsafeIntToNat
, fmapPeerPipelined
) where
import Unsafe.Coerce (unsafeCoerce)
import Network.TypedProtocol.Core
data PeerPipelined ps (pr :: PeerRole) (st :: ps) m a where
PeerPipelined :: PeerSender ps pr st Z c m a
-> PeerPipelined ps pr st m a
deriving instance Functor m => Functor (PeerPipelined ps (pr :: PeerRole) (st :: ps) m)
fmapPeerPipelined :: (forall c. PeerSender ps pr st Z c m a -> PeerSender ps' pr st' Z c m b)
-> PeerPipelined ps pr st m a
-> PeerPipelined ps' pr st' m b
fmapPeerPipelined :: (forall c.
PeerSender ps pr st 'Z c m a -> PeerSender ps' pr st' 'Z c m b)
-> PeerPipelined ps pr st m a -> PeerPipelined ps' pr st' m b
fmapPeerPipelined forall c.
PeerSender ps pr st 'Z c m a -> PeerSender ps' pr st' 'Z c m b
f (PeerPipelined PeerSender ps pr st 'Z c m a
peer) = PeerSender ps' pr st' 'Z c m b -> PeerPipelined ps' pr st' m b
forall ps (pr :: PeerRole) (st :: ps) c (m :: * -> *) a.
PeerSender ps pr st 'Z c m a -> PeerPipelined ps pr st m a
PeerPipelined (PeerSender ps pr st 'Z c m a -> PeerSender ps' pr st' 'Z c m b
forall c.
PeerSender ps pr st 'Z c m a -> PeerSender ps' pr st' 'Z c m b
f PeerSender ps pr st 'Z c m a
peer)
data PeerSender ps (pr :: PeerRole) (st :: ps) (n :: Outstanding) c m a where
SenderEffect :: m (PeerSender ps pr st n c m a)
-> PeerSender ps pr st n c m a
SenderDone :: !(NobodyHasAgency st)
-> a
-> PeerSender ps pr st Z c m a
SenderYield :: !(WeHaveAgency pr st)
-> Message ps st st'
-> PeerSender ps pr st' Z c m a
-> PeerSender ps pr st Z c m a
SenderAwait :: !(TheyHaveAgency pr st)
-> (forall st'. Message ps st st'
-> PeerSender ps pr st' Z c m a)
-> PeerSender ps pr st Z c m a
SenderPipeline :: !(WeHaveAgency pr st)
-> Message ps st st'
-> PeerReceiver ps pr (st' :: ps) (st'' :: ps) m c
-> PeerSender ps pr (st'' :: ps) (S n) c m a
-> PeerSender ps pr (st :: ps) n c m a
SenderCollect :: Maybe (PeerSender ps pr (st :: ps) (S n) c m a)
-> (c -> PeerSender ps pr (st :: ps) n c m a)
-> PeerSender ps pr (st :: ps) (S n) c m a
deriving instance Functor m => Functor (PeerSender ps (pr :: PeerRole) (st :: ps) (n :: Outstanding) c m)
data PeerReceiver ps (pr :: PeerRole) (st :: ps) (stdone :: ps) m c where
ReceiverEffect :: m (PeerReceiver ps pr st stdone m c)
-> PeerReceiver ps pr st stdone m c
ReceiverDone :: c -> PeerReceiver ps pr stdone stdone m c
ReceiverAwait :: !(TheyHaveAgency pr st)
-> (forall st'. Message ps st st'
-> PeerReceiver ps pr st' stdone m c)
-> PeerReceiver ps pr st stdone m c
type Outstanding = N
data N = Z | S N
newtype Nat (n :: N) = UnsafeInt Int
deriving Int -> Nat n -> ShowS
[Nat n] -> ShowS
Nat n -> String
(Int -> Nat n -> ShowS)
-> (Nat n -> String) -> ([Nat n] -> ShowS) -> Show (Nat n)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (n :: Outstanding). Int -> Nat n -> ShowS
forall (n :: Outstanding). [Nat n] -> ShowS
forall (n :: Outstanding). Nat n -> String
showList :: [Nat n] -> ShowS
$cshowList :: forall (n :: Outstanding). [Nat n] -> ShowS
show :: Nat n -> String
$cshow :: forall (n :: Outstanding). Nat n -> String
showsPrec :: Int -> Nat n -> ShowS
$cshowsPrec :: forall (n :: Outstanding). Int -> Nat n -> ShowS
Show via Int
data IsNat (n :: N) where
IsZero :: IsNat Z
IsSucc :: Nat n -> IsNat (S n)
toIsNat :: Nat n -> IsNat n
toIsNat :: Nat n -> IsNat n
toIsNat (UnsafeInt Int
0) = IsNat 'Z -> IsNat n
forall a b. a -> b
unsafeCoerce IsNat 'Z
IsZero
toIsNat (UnsafeInt Int
n) = IsNat ('S Any) -> IsNat n
forall a b. a -> b
unsafeCoerce (Nat Any -> IsNat ('S Any)
forall (n :: Outstanding). Nat n -> IsNat ('S n)
IsSucc (Int -> Nat Any
forall (n :: Outstanding). Int -> Nat n
UnsafeInt (Int -> Int
forall a. Enum a => a -> a
pred Int
n)))
pattern Zero :: () => Z ~ n => Nat n
pattern $bZero :: Nat n
$mZero :: forall r (n :: Outstanding).
Nat n -> (('Z ~ n) => r) -> (Void# -> r) -> r
Zero <- (toIsNat -> IsZero) where
Zero = Int -> Nat n
forall (n :: Outstanding). Int -> Nat n
UnsafeInt Int
0
pattern Succ :: () => (m ~ S n) => Nat n -> Nat m
pattern $bSucc :: Nat n -> Nat m
$mSucc :: forall r (m :: Outstanding).
Nat m
-> (forall (n :: Outstanding). (m ~ 'S n) => Nat n -> r)
-> (Void# -> r)
-> r
Succ n <- (toIsNat -> IsSucc n) where
Succ (UnsafeInt Int
n) = Int -> Nat m
forall (n :: Outstanding). Int -> Nat n
UnsafeInt (Int -> Int
forall a. Enum a => a -> a
succ Int
n)
{-# COMPLETE Zero, Succ #-}
natToInt :: Nat n -> Int
natToInt :: Nat n -> Int
natToInt (UnsafeInt Int
n) = Int
n
unsafeIntToNat :: Int -> Nat n
unsafeIntToNat :: Int -> Nat n
unsafeIntToNat = Int -> Nat n
forall (n :: Outstanding). Int -> Nat n
UnsafeInt