{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | Unagi-Chan Bounded Transport Instance.
-- 
-- This makes use of a KnownNat parameter to specify the size of the buffer.
-- 
module Control.Churro.Transport.Unagi.Bounded where
    
import Control.Churro.Types
import Control.Churro.Prelude

import Control.Concurrent.Chan.Unagi.Bounded
import Data.Void
import Data.Data (Proxy(..))
import GHC.TypeLits (KnownNat, natVal)

-- $setup
-- 
-- Test Setup
-- 
-- >>> :set -XDataKinds
-- >>> import Control.Churro

data UnagiBounded n a

instance KnownNat n => Transport (UnagiBounded n) where
    data In  (UnagiBounded n) a = ChanIn  (InChan  a)
    data Out (UnagiBounded n) a = ChanOut (OutChan a)
    yank :: Out (UnagiBounded n) a -> IO a
yank (ChanOut c) = OutChan a -> IO a
forall a. OutChan a -> IO a
readChan  OutChan a
c
    yeet :: In (UnagiBounded n) a -> a -> IO ()
yeet (ChanIn  c) = InChan a -> a -> IO ()
forall a. InChan a -> a -> IO ()
writeChan InChan a
c
    flex :: IO (In (UnagiBounded n) a, Out (UnagiBounded n) a)
flex = do 
        (InChan a
i, OutChan a
o) <- Int -> IO (InChan a, OutChan a)
forall a. Int -> IO (InChan a, OutChan a)
newChan (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n
forall k (t :: k). Proxy t
Proxy :: Proxy n)))
        (In (UnagiBounded n) a, Out (UnagiBounded n) a)
-> IO (In (UnagiBounded n) a, Out (UnagiBounded n) a)
forall (m :: * -> *) a. Monad m => a -> m a
return (InChan a -> In (UnagiBounded n) a
forall (n :: Nat) a. InChan a -> In (UnagiBounded n) a
ChanIn InChan a
i, OutChan a -> Out (UnagiBounded n) a
forall (n :: Nat) a. OutChan a -> Out (UnagiBounded n) a
ChanOut OutChan a
o)

type ChurroUnagiBounded n = Churro (UnagiBounded n)

-- | Convenience function for running a Churro with a Bounded Unagi-Chan Transport.
-- 
runWaitUnagi :: KnownNat n => ChurroUnagiBounded n Void Void -> IO ()
runWaitUnagi :: ChurroUnagiBounded n Void Void -> IO ()
runWaitUnagi = ChurroUnagiBounded n Void Void -> IO ()
forall (t :: * -> *). Transport t => Churro t Void Void -> IO ()
runWait

-- | Convenience function for running a Churro into a List with a Bounded Unagi-Chan Transport.
-- 
-- >>> runWaitListUnagi @10 $ sourceList [1,2,3] >>> arr succ
-- [2,3,4]
runWaitListUnagi :: KnownNat n => ChurroUnagiBounded n Void o -> IO [o]
runWaitListUnagi :: ChurroUnagiBounded n Void o -> IO [o]
runWaitListUnagi = ChurroUnagiBounded n Void o -> IO [o]
forall (t :: * -> *) o. Transport t => Churro t Void o -> IO [o]
runWaitList