packages feed

calamity 0.1.7.0 → 0.1.8.0

raw patch · 8 files changed

+404/−141 lines, 8 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Calamity.Client.Types: instance (Calamity.Client.Types.EHInstanceSelector a GHC.Types.~ flag, Calamity.Client.Types.GetEventHandlers' flag a m) => Calamity.Client.Types.GetEventHandlers a m
- Calamity.Client.Types: instance (Calamity.Client.Types.EHInstanceSelector a GHC.Types.~ flag, Calamity.Client.Types.InsertEventHandler' flag a m) => Calamity.Client.Types.InsertEventHandler a m
- Calamity.Client.Types: instance (Data.Typeable.Internal.Typeable s, Calamity.Client.Types.EHStorageType s GHC.Types.~ [Data.Dynamic.Dynamic], Data.Typeable.Internal.Typeable (Calamity.Client.Types.EHType s m)) => Calamity.Client.Types.InsertEventHandler' 'GHC.Types.False s m
- Calamity.Client.Types: instance (Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable (Calamity.Client.Types.EHType s m), Calamity.Client.Types.EHStorageType s GHC.Types.~ [Data.Dynamic.Dynamic]) => Calamity.Client.Types.GetEventHandlers' 'GHC.Types.False s m
- Calamity.Client.Types: instance forall a1 s1 (a2 :: a1) (s2 :: s1) (m :: * -> *). (Data.Typeable.Internal.Typeable a2, Data.Typeable.Internal.Typeable s2, Data.Typeable.Internal.Typeable (Calamity.Client.Types.EHType ('Calamity.Client.Types.CustomEvt s2 a2) m)) => Calamity.Client.Types.GetEventHandlers' 'GHC.Types.True ('Calamity.Client.Types.CustomEvt s2 a2) m
- Calamity.Client.Types: instance forall a1 s1 (a2 :: a1) (s2 :: s1) (m :: * -> *). (Data.Typeable.Internal.Typeable a2, Data.Typeable.Internal.Typeable s2, Data.Typeable.Internal.Typeable (Calamity.Client.Types.EHType ('Calamity.Client.Types.CustomEvt s2 a2) m)) => Calamity.Client.Types.InsertEventHandler' 'GHC.Types.True ('Calamity.Client.Types.CustomEvt s2 a2) m
+ Calamity.Client.Client: waitUntil :: forall (s :: EventType) r t eh ehB. (BotC r, InsertEventHandler s, RemoveEventHandler s, Uncurry eh, eh ~ EHType s (Sem r) (), eh ~ Curried (t -> Sem r ()), Uncurry ehB, Uncurried ehB ~ (t -> Sem r Bool), Curry (t -> IO ()), Curried (t -> IO ()) ~ EHType s IO ()) => ehB -> Sem r t
+ Calamity.Client.Types: StartupError :: String -> StartupError
+ Calamity.Client.Types: [$sel:ehidCounter:Client] :: Client -> IORef Integer
+ Calamity.Client.Types: [$sel:originalEffectsType:Client] :: Client -> TypeRep
+ Calamity.Client.Types: class RemoveEventHandler a
+ Calamity.Client.Types: instance (Calamity.Client.Types.EHInstanceSelector a GHC.Types.~ flag, Calamity.Client.Types.GetEventHandlers' flag a) => Calamity.Client.Types.GetEventHandlers a
+ Calamity.Client.Types: instance (Calamity.Client.Types.EHInstanceSelector a GHC.Types.~ flag, Calamity.Client.Types.InsertEventHandler' flag a) => Calamity.Client.Types.InsertEventHandler a
+ Calamity.Client.Types: instance (Calamity.Client.Types.EHInstanceSelector a GHC.Types.~ flag, Calamity.Client.Types.RemoveEventHandler' flag a) => Calamity.Client.Types.RemoveEventHandler a
+ Calamity.Client.Types: instance (Data.Typeable.Internal.Typeable s, Calamity.Client.Types.EHStorageType s GHC.Types.~ [Calamity.Client.Types.EventHandlerWithID (Calamity.Client.Types.StoredEHType s)], Data.Typeable.Internal.Typeable (Calamity.Client.Types.StoredEHType s)) => Calamity.Client.Types.InsertEventHandler' 'GHC.Types.False s
+ Calamity.Client.Types: instance (Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable (Calamity.Client.Types.StoredEHType s), Calamity.Client.Types.EHStorageType s GHC.Types.~ [Calamity.Client.Types.EventHandlerWithID (Calamity.Client.Types.StoredEHType s)]) => Calamity.Client.Types.GetEventHandlers' 'GHC.Types.False s
+ Calamity.Client.Types: instance (Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable (Calamity.Client.Types.StoredEHType s), Calamity.Client.Types.EHStorageType s GHC.Types.~ [Calamity.Client.Types.EventHandlerWithID (Calamity.Client.Types.StoredEHType s)]) => Calamity.Client.Types.RemoveEventHandler' 'GHC.Types.False s
+ Calamity.Client.Types: instance GHC.Show.Show Calamity.Client.Types.StartupError
+ Calamity.Client.Types: instance forall s1 a (s2 :: s1). (Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable s2, Data.Typeable.Internal.Typeable (Calamity.Client.Types.StoredEHType ('Calamity.Client.Types.CustomEvt s2 a)), Calamity.Client.Types.EHType ('Calamity.Client.Types.CustomEvt s2 a) GHC.Types.IO () GHC.Types.~ (a -> GHC.Types.IO ())) => Calamity.Client.Types.InsertEventHandler' 'GHC.Types.True ('Calamity.Client.Types.CustomEvt s2 a)
+ Calamity.Client.Types: instance forall s1 a1 (s2 :: s1) (a2 :: a1). (Data.Typeable.Internal.Typeable s2, Data.Typeable.Internal.Typeable a2) => Calamity.Client.Types.RemoveEventHandler' 'GHC.Types.True ('Calamity.Client.Types.CustomEvt s2 a2)
+ Calamity.Client.Types: instance forall s1 a1 (s2 :: s1) (a2 :: a1). Calamity.Client.Types.GetEventHandlers' 'GHC.Types.True ('Calamity.Client.Types.CustomEvt s2 a2)
+ Calamity.Client.Types: newtype StartupError
+ Calamity.Client.Types: removeEventHandler :: RemoveEventHandler a => Proxy a -> Integer -> EventHandlers -> EventHandlers
+ Calamity.Internal.GenericCurry: class Curry t where {
+ Calamity.Internal.GenericCurry: class Uncurry t where {
+ Calamity.Internal.GenericCurry: curryG :: Curry t => t -> Curried t
+ Calamity.Internal.GenericCurry: instance (Calamity.Internal.GenericCurry.CurryInstanceSelector t GHC.Types.~ flag, Calamity.Internal.GenericCurry.Curry' flag t) => Calamity.Internal.GenericCurry.Curry t
+ Calamity.Internal.GenericCurry: instance (Calamity.Internal.GenericCurry.CurryInstanceSelector t GHC.Types.~ flag, Calamity.Internal.GenericCurry.Uncurry' flag t) => Calamity.Internal.GenericCurry.Uncurry t
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Curry' 1 (a -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Curry' 2 ((a, b) -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Curry' 3 ((a, b, c) -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Curry' 4 ((a, b, c, d) -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Curry' 5 ((a, b, c, d, e) -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Curry' 6 ((a, b, c, d, e, f) -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Uncurry' 1 (a -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Uncurry' 2 (a -> b -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Uncurry' 3 (a -> b -> c -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Uncurry' 4 (a -> b -> c -> d -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Uncurry' 5 (a -> b -> c -> d -> e -> r)
+ Calamity.Internal.GenericCurry: instance Calamity.Internal.GenericCurry.Uncurry' 6 (a -> b -> c -> d -> e -> f -> r)
+ Calamity.Internal.GenericCurry: type family Uncurried t;
+ Calamity.Internal.GenericCurry: uncurryG :: Uncurry t => t -> Uncurried t
+ Calamity.Internal.GenericCurry: }
+ Calamity.Internal.RunIntoIO: [IntoIO] :: (p -> m ()) -> IntoIO p m (p -> IO ())
+ Calamity.Internal.RunIntoIO: data IntoIO p m a
+ Calamity.Internal.RunIntoIO: intoIO :: forall p_axeY r_axwF. MemberWithError (IntoIO p_axeY) r_axwF => (p_axeY -> Sem r_axwF ()) -> Sem r_axwF (p_axeY -> IO ())
+ Calamity.Internal.RunIntoIO: runIntoIOFinal :: forall r p a. Member (Final IO) r => Sem (IntoIO p : r) a -> Sem r a
- Calamity.Cache.Eff: delDM :: forall r_a9GZT. MemberWithError CacheEff r_a9GZT => Snowflake DMChannel -> Sem r_a9GZT ()
+ Calamity.Cache.Eff: delDM :: forall r_a9HL6. MemberWithError CacheEff r_a9HL6 => Snowflake DMChannel -> Sem r_a9HL6 ()
- Calamity.Cache.Eff: delGuild :: forall r_a9GZM. MemberWithError CacheEff r_a9GZM => Snowflake Guild -> Sem r_a9GZM ()
+ Calamity.Cache.Eff: delGuild :: forall r_a9HKZ. MemberWithError CacheEff r_a9HKZ => Snowflake Guild -> Sem r_a9HKZ ()
- Calamity.Cache.Eff: delMessage :: forall r_a9H0e. MemberWithError CacheEff r_a9H0e => Snowflake Message -> Sem r_a9H0e ()
+ Calamity.Cache.Eff: delMessage :: forall r_a9HLr. MemberWithError CacheEff r_a9HLr => Snowflake Message -> Sem r_a9HLr ()
- Calamity.Cache.Eff: delUnavailableGuild :: forall r_a9H07. MemberWithError CacheEff r_a9H07 => Snowflake Guild -> Sem r_a9H07 ()
+ Calamity.Cache.Eff: delUnavailableGuild :: forall r_a9HLk. MemberWithError CacheEff r_a9HLk => Snowflake Guild -> Sem r_a9HLk ()
- Calamity.Cache.Eff: delUser :: forall r_a9H00. MemberWithError CacheEff r_a9H00 => Snowflake User -> Sem r_a9H00 ()
+ Calamity.Cache.Eff: delUser :: forall r_a9HLd. MemberWithError CacheEff r_a9HLd => Snowflake User -> Sem r_a9HLd ()
- Calamity.Cache.Eff: getBotUser :: forall r_a9GZG. MemberWithError CacheEff r_a9GZG => Sem r_a9GZG (Maybe User)
+ Calamity.Cache.Eff: getBotUser :: forall r_a9HKT. MemberWithError CacheEff r_a9HKT => Sem r_a9HKT (Maybe User)
- Calamity.Cache.Eff: getDM :: forall r_a9GZQ. MemberWithError CacheEff r_a9GZQ => Snowflake DMChannel -> Sem r_a9GZQ (Maybe DMChannel)
+ Calamity.Cache.Eff: getDM :: forall r_a9HL3. MemberWithError CacheEff r_a9HL3 => Snowflake DMChannel -> Sem r_a9HL3 (Maybe DMChannel)
- Calamity.Cache.Eff: getDMs :: forall r_a9GZS. MemberWithError CacheEff r_a9GZS => Sem r_a9GZS [DMChannel]
+ Calamity.Cache.Eff: getDMs :: forall r_a9HL5. MemberWithError CacheEff r_a9HL5 => Sem r_a9HL5 [DMChannel]
- Calamity.Cache.Eff: getGuild :: forall r_a9GZJ. MemberWithError CacheEff r_a9GZJ => Snowflake Guild -> Sem r_a9GZJ (Maybe Guild)
+ Calamity.Cache.Eff: getGuild :: forall r_a9HKW. MemberWithError CacheEff r_a9HKW => Snowflake Guild -> Sem r_a9HKW (Maybe Guild)
- Calamity.Cache.Eff: getGuilds :: forall r_a9GZL. MemberWithError CacheEff r_a9GZL => Sem r_a9GZL [Guild]
+ Calamity.Cache.Eff: getGuilds :: forall r_a9HKY. MemberWithError CacheEff r_a9HKY => Sem r_a9HKY [Guild]
- Calamity.Cache.Eff: getMessage :: forall r_a9H0b. MemberWithError CacheEff r_a9H0b => Snowflake Message -> Sem r_a9H0b (Maybe Message)
+ Calamity.Cache.Eff: getMessage :: forall r_a9HLo. MemberWithError CacheEff r_a9HLo => Snowflake Message -> Sem r_a9HLo (Maybe Message)
- Calamity.Cache.Eff: getMessages :: forall r_a9H0d. MemberWithError CacheEff r_a9H0d => Sem r_a9H0d [Message]
+ Calamity.Cache.Eff: getMessages :: forall r_a9HLq. MemberWithError CacheEff r_a9HLq => Sem r_a9HLq [Message]
- Calamity.Cache.Eff: getUnavailableGuilds :: forall r_a9H06. MemberWithError CacheEff r_a9H06 => Sem r_a9H06 [Snowflake Guild]
+ Calamity.Cache.Eff: getUnavailableGuilds :: forall r_a9HLj. MemberWithError CacheEff r_a9HLj => Sem r_a9HLj [Snowflake Guild]
- Calamity.Cache.Eff: getUser :: forall r_a9GZX. MemberWithError CacheEff r_a9GZX => Snowflake User -> Sem r_a9GZX (Maybe User)
+ Calamity.Cache.Eff: getUser :: forall r_a9HLa. MemberWithError CacheEff r_a9HLa => Snowflake User -> Sem r_a9HLa (Maybe User)
- Calamity.Cache.Eff: getUsers :: forall r_a9GZZ. MemberWithError CacheEff r_a9GZZ => Sem r_a9GZZ [User]
+ Calamity.Cache.Eff: getUsers :: forall r_a9HLc. MemberWithError CacheEff r_a9HLc => Sem r_a9HLc [User]
- Calamity.Cache.Eff: isUnavailableGuild :: forall r_a9H04. MemberWithError CacheEff r_a9H04 => Snowflake Guild -> Sem r_a9H04 Bool
+ Calamity.Cache.Eff: isUnavailableGuild :: forall r_a9HLh. MemberWithError CacheEff r_a9HLh => Snowflake Guild -> Sem r_a9HLh Bool
- Calamity.Cache.Eff: setBotUser :: forall r_a9GZE. MemberWithError CacheEff r_a9GZE => User -> Sem r_a9GZE ()
+ Calamity.Cache.Eff: setBotUser :: forall r_a9HKR. MemberWithError CacheEff r_a9HKR => User -> Sem r_a9HKR ()
- Calamity.Cache.Eff: setDM :: forall r_a9GZO. MemberWithError CacheEff r_a9GZO => DMChannel -> Sem r_a9GZO ()
+ Calamity.Cache.Eff: setDM :: forall r_a9HL1. MemberWithError CacheEff r_a9HL1 => DMChannel -> Sem r_a9HL1 ()
- Calamity.Cache.Eff: setGuild :: forall r_a9GZH. MemberWithError CacheEff r_a9GZH => Guild -> Sem r_a9GZH ()
+ Calamity.Cache.Eff: setGuild :: forall r_a9HKU. MemberWithError CacheEff r_a9HKU => Guild -> Sem r_a9HKU ()
- Calamity.Cache.Eff: setMessage :: forall r_a9H09. MemberWithError CacheEff r_a9H09 => Message -> Sem r_a9H09 ()
+ Calamity.Cache.Eff: setMessage :: forall r_a9HLm. MemberWithError CacheEff r_a9HLm => Message -> Sem r_a9HLm ()
- Calamity.Cache.Eff: setUnavailableGuild :: forall r_a9H02. MemberWithError CacheEff r_a9H02 => Snowflake Guild -> Sem r_a9H02 ()
+ Calamity.Cache.Eff: setUnavailableGuild :: forall r_a9HLf. MemberWithError CacheEff r_a9HLf => Snowflake Guild -> Sem r_a9HLf ()
- Calamity.Cache.Eff: setUser :: forall r_a9GZV. MemberWithError CacheEff r_a9GZV => User -> Sem r_a9GZV ()
+ Calamity.Cache.Eff: setUser :: forall r_a9HL8. MemberWithError CacheEff r_a9HL8 => User -> Sem r_a9HL8 ()
- Calamity.Client.Client: react :: forall (s :: EventType) r. (BotC r, InsertEventHandler s (Sem r)) => EHType s (Sem r) -> Sem r ()
+ Calamity.Client.Client: react :: forall (s :: EventType) r t eh ehIO. (BotC r, InsertEventHandler s, RemoveEventHandler s, eh ~ EHType s (Sem r) (), ehIO ~ EHType s IO (), Uncurry eh, Uncurried eh ~ (t -> Sem r ()), Curry (t -> IO ()), ehIO ~ Curried (t -> IO ())) => eh -> Sem r (Sem r ())
- Calamity.Client.Client: runBotIO :: (Members '[Embed IO, Final IO, Fail, CacheEff, MetricEff] r, Typeable r) => Token -> SetupEff r -> Sem r ()
+ Calamity.Client.Client: runBotIO :: forall r a. (Members '[Embed IO, Final IO, CacheEff, MetricEff] r, Typeable (SetupEff r)) => Token -> Sem (SetupEff r) a -> Sem r (Maybe StartupError)
- Calamity.Client.ShardManager: shardBot :: (BotC r, Member Fail r) => Sem r ()
+ Calamity.Client.ShardManager: shardBot :: BotC r => Sem r (Either StartupError ())
- Calamity.Client.Types: Client :: TVar [(InChan ControlMessage, Async (Maybe ()))] -> MVar Int -> Token -> RateLimitState -> InChan CalamityEvent -> OutChan CalamityEvent -> Client
+ Calamity.Client.Types: Client :: TVar [(InChan ControlMessage, Async (Maybe ()))] -> MVar Int -> Token -> RateLimitState -> InChan CalamityEvent -> OutChan CalamityEvent -> IORef Integer -> TypeRep -> Client
- Calamity.Client.Types: class InsertEventHandler a m
+ Calamity.Client.Types: class InsertEventHandler a
- Calamity.Client.Types: getCustomEventHandlers :: TypeRep -> TypeRep -> EventHandlers -> [Dynamic]
+ Calamity.Client.Types: getCustomEventHandlers :: TypeRep -> TypeRep -> EventHandlers -> [Dynamic -> IO ()]
- Calamity.Client.Types: getEventHandlers :: GetEventHandlers a m => EventHandlers -> [EHType a m]
+ Calamity.Client.Types: getEventHandlers :: GetEventHandlers a => EventHandlers -> [StoredEHType a]
- Calamity.Client.Types: makeEventHandlers :: InsertEventHandler a m => Proxy a -> Proxy m -> EHType a m -> EventHandlers
+ Calamity.Client.Types: makeEventHandlers :: InsertEventHandler a => Proxy a -> Integer -> StoredEHType a -> EventHandlers
- Calamity.Client.Types: type SetupEff r = Sem (LogEff : Reader Client : AtomicState EventHandlers : Async : r) ()
+ Calamity.Client.Types: type SetupEff r = (LogEff : Reader Client : AtomicState EventHandlers : Async : r)
- Calamity.Client.Types: type family EHType (d :: EventType) m
+ Calamity.Client.Types: type family EHType (d :: EventType) m r
- Calamity.Metrics.Eff: addCounter :: forall r_aEdR. MemberWithError MetricEff r_aEdR => Int -> Counter -> Sem r_aEdR Int
+ Calamity.Metrics.Eff: addCounter :: forall r_aF2T. MemberWithError MetricEff r_aF2T => Int -> Counter -> Sem r_aF2T Int
- Calamity.Metrics.Eff: modifyGauge :: forall r_aEdU. MemberWithError MetricEff r_aEdU => (Double -> Double) -> Gauge -> Sem r_aEdU Double
+ Calamity.Metrics.Eff: modifyGauge :: forall r_aF2W. MemberWithError MetricEff r_aF2W => (Double -> Double) -> Gauge -> Sem r_aF2W Double
- Calamity.Metrics.Eff: observeHistogram :: forall r_aEdX. MemberWithError MetricEff r_aEdX => Double -> Histogram -> Sem r_aEdX HistogramSample
+ Calamity.Metrics.Eff: observeHistogram :: forall r_aF2Z. MemberWithError MetricEff r_aF2Z => Double -> Histogram -> Sem r_aF2Z HistogramSample
- Calamity.Metrics.Eff: registerCounter :: forall r_aEdH. MemberWithError MetricEff r_aEdH => Text -> [(Text, Text)] -> Sem r_aEdH Counter
+ Calamity.Metrics.Eff: registerCounter :: forall r_aF2J. MemberWithError MetricEff r_aF2J => Text -> [(Text, Text)] -> Sem r_aF2J Counter
- Calamity.Metrics.Eff: registerGauge :: forall r_aEdK. MemberWithError MetricEff r_aEdK => Text -> [(Text, Text)] -> Sem r_aEdK Gauge
+ Calamity.Metrics.Eff: registerGauge :: forall r_aF2M. MemberWithError MetricEff r_aF2M => Text -> [(Text, Text)] -> Sem r_aF2M Gauge
- Calamity.Metrics.Eff: registerHistogram :: forall r_aEdN. MemberWithError MetricEff r_aEdN => Text -> [(Text, Text)] -> [Double] -> Sem r_aEdN Histogram
+ Calamity.Metrics.Eff: registerHistogram :: forall r_aF2P. MemberWithError MetricEff r_aF2P => Text -> [(Text, Text)] -> [Double] -> Sem r_aF2P Histogram

Files

ChangeLog.md view
@@ -1,5 +1,12 @@ # Changelog for Calamity +## 0.1.8.0++*2020-05-15*++* Did a large rework of how event handlers are stored internally.+* introduced `waitUntil`+ ## 0.1.4.0  * Added back extra exports of `Calamity.Types.Partial` from
README.md view
@@ -83,7 +83,7 @@  P.makeSem ''Counter -runCounterAtomic :: P.Member (P.Embed IO) r => P.Sem (Counter ': r) () -> P.Sem r ()+runCounterAtomic :: P.Member (P.Embed IO) r => P.Sem (Counter ': r) a -> P.Sem r a runCounterAtomic m = do   var <- P.embed $ newTVarIO (0 :: Int)   P.runAtomicStateTVar var $ P.reinterpret (\case@@ -95,27 +95,23 @@     Left e -> DiP.error (e ^. packed)     _      -> pure () -handleFailByPrinting m = do-  r <- P.runFail m-  case r of-    Left e -> P.embed $ print (show e)-    _      -> pure ()- info = DiP.info @Text debug = DiP.info @Text +tellt :: (BotC r, Tellable t) => t -> Text -> P.Sem r (Either RestError Message) tellt = tell @Text  main :: IO () main = do   token <- view packed <$> getEnv "BOT_TOKEN"-  P.runFinal . P.embedToFinal . handleFailByPrinting . runCounterAtomic . runCacheInMemory . runMetricsNoop-    $ runBotIO (BotToken token) $ react @'MessageCreateEvt $ \msg -> handleFailByLogging $ do-      when (msg ^. #content == "!count") $ replicateM_ 3 $ do+  void . P.runFinal . P.embedToFinal . runCounterAtomic . runCacheInMemory . runMetricsPrometheusIO+    $ runBotIO (BotToken token) $ do+    react @'MessageCreateEvt $ \msg -> handleFailByLogging $ case msg ^. #content of+      "!count" -> replicateM_ 3 $ do         val <- getCounter         info $ "the counter is: " <> showt val         void $ tellt msg ("The value is: " <> showt val)-      when (msg ^. #content == "!say hi") $ replicateM_ 3 . P.async $ do+      "!say hi" -> replicateM_ 3 . P.async $ do         info "saying heya"         Right msg' <- tellt msg "heya"         info "sleeping"@@ -123,10 +119,18 @@         info "slept"         void . invoke $ EditMessage (msg ^. #channelID) msg' (Just "lol") Nothing         info "edited"-      when (msg ^. #content == "!explode") $ do+      "!explode" -> do         Just x <- pure Nothing         debug "unreachable!"-      when (msg ^. #content == "!bye") $ do+      "!bye" -> do         void $ tellt msg "bye!"         stopBot+      "!fire-evt" -> fire $ customEvt @"my-event" ("aha" :: Text, msg)+      "!wait" -> do+        void $ tellt msg "waiting for !continue"+        waitUntil @'MessageCreateEvt (\msg -> (debug $ "got message: " <> showt msg) >> (pure $ msg ^. #content == "!continue"))+        void $ tellt msg "got !continue"+      _ -> pure ()+    react @('CustomEvt "my-event" (Text, Message)) $ \(s, m) ->+      void $ tellt m ("Somebody told me to tell you about: " <> s) ```
calamity.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 0b61f91df75a0a06757763a207ce83d2a9597c059dadd7798a155ace29013568+-- hash: 1217175ab8de3749a8fdae8f73f44a650fbb177f93f65f8c2d583dea7cffec7c  name:           calamity-version:        0.1.7.0+version:        0.1.8.0 synopsis:       A library for writing discord bots description:    Please see the README on GitHub at <https://github.com/nitros12/calamity#readme> category:       Network, Web@@ -60,6 +60,8 @@       Calamity.HTTP.Webhook       Calamity.Internal.AesonThings       Calamity.Internal.BoundedStore+      Calamity.Internal.GenericCurry+      Calamity.Internal.RunIntoIO       Calamity.Internal.SnowflakeMap       Calamity.Internal.Updateable       Calamity.Internal.Utils
src/Calamity/Client/Client.hs view
@@ -8,6 +8,7 @@     , sendPresence     , events     , fire+    , waitUntil     , CalamityEvent(Dispatch, ShutDown)     , customEvt ) where @@ -17,8 +18,10 @@ import           Calamity.Gateway.DispatchEvents import           Calamity.Gateway.Types import           Calamity.HTTP.Internal.Ratelimit+import           Calamity.Internal.GenericCurry import qualified Calamity.Internal.SnowflakeMap   as SM import           Calamity.Internal.Updateable+import           Calamity.Internal.RunIntoIO import           Calamity.Internal.Utils import           Calamity.Metrics.Eff import           Calamity.Types.Model.Channel@@ -30,12 +33,14 @@ import           Control.Concurrent.Chan.Unagi import           Control.Concurrent.MVar import           Control.Concurrent.STM+import           Control.Exception                ( SomeException ) import           Control.Lens import           Control.Monad  import           Data.Default.Class import           Data.Dynamic import           Data.Foldable+import           Data.IORef import           Data.Maybe import           Data.Proxy import           Data.Time.Clock.POSIX@@ -62,12 +67,13 @@   pure (duration, res)  -newClient :: Token -> IO Client-newClient token = do+newClient :: Token -> TypeRep -> IO Client+newClient token t = do   shards'        <- newTVarIO []   numShards'     <- newEmptyMVar   rlState'       <- newRateLimitState   (inc, outc)    <- newChan+  ehidCounter    <- newIORef 0    pure $ Client shards'                 numShards'@@ -75,22 +81,30 @@                 rlState'                 inc                 outc+                ehidCounter+                t  -- | Create a bot, run your setup action, and then loop until the bot closes.------ This method has a 'P.Fail' effect to handle fatal errors that happen during--- setup (bad token, etc).-runBotIO :: (P.Members '[P.Embed IO, P.Final IO, P.Fail, CacheEff, MetricEff] r, Typeable r) => Token -> SetupEff r -> P.Sem r ()+runBotIO :: forall r a. (P.Members '[P.Embed IO, P.Final IO, CacheEff, MetricEff] r, Typeable (SetupEff r)) => Token -> P.Sem (SetupEff r) a -> P.Sem r (Maybe StartupError) runBotIO token setup = do-  client <- P.embed $ newClient token+  client <- P.embed $ newClient token (typeRep $ Proxy @(SetupEff r))   handlers <- P.embed $ newTVarIO def   P.asyncToIOFinal . P.runAtomicStateTVar handlers . P.runReader client . Di.runDiToStderrIO . Di.push "calamity" $ do-    Di.push "calamity-setup" setup-    shardBot-    Di.push "calamity-loop" clientLoop-    Di.push "calamity-stop" finishUp+    void $ Di.push "calamity-setup" setup+    r <- shardBot+    case r of+      Left e -> pure (Just e)+      Right _ -> do+        Di.push "calamity-loop" clientLoop+        Di.push "calamity-stop" finishUp+        pure Nothing --- | Register an event handler.+ehToIO :: forall r p. P.Member (P.Final IO) r => (p -> P.Sem r ()) -> P.Sem r (p -> IO ())+ehToIO f = runIntoIOFinal go+  where go :: P.Sem (IntoIO p ': r) (p -> IO ())+        go = intoIO (P.raise . f)++-- | Register an event handler, returning an action that removes the event handler from the bot. -- -- Refer to 'EventType' for what events you can register, and 'EHType' for the -- parameters the event handlers they receive.@@ -118,10 +132,30 @@ -- This function is pretty bad for giving nasty type errors, -- since if something doesn't match then 'EHType' might not get substituted, -- which will result in errors about parameter counts mismatching.-react :: forall (s :: EventType) r. (BotC r, InsertEventHandler s (P.Sem r)) => EHType s (P.Sem r) -> P.Sem r ()-react handler = let handlers = makeEventHandlers (Proxy @s) (Proxy @(P.Sem r)) handler-                in P.atomicModify (handlers <>)+react :: forall (s :: EventType) r t eh ehIO.+      (BotC r+      , InsertEventHandler s+      , RemoveEventHandler s+      , eh ~ EHType s (P.Sem r) ()+      , ehIO ~ EHType s IO ()+      , Uncurry eh+      , Uncurried eh ~ (t -> P.Sem r ())+      , Curry (t -> IO ())+      , ehIO ~ Curried (t -> IO ())+      )+      => eh+      -> P.Sem r (P.Sem r ())+react handler = do+  handler' <- ehToIO (\(params :: t) -> (uncurryG handler params))+  ehidC <- P.asks (^. #ehidCounter)+  id' <- P.embed $ atomicModifyIORef ehidC (\i -> (succ i, i))+  let handlers = makeEventHandlers (Proxy @s) id' (curryG handler')+  P.atomicModify (handlers <>)+  pure $ removeHandler @s id' +removeHandler :: forall (s :: EventType) r. (BotC r, RemoveEventHandler s) => Integer -> P.Sem r ()+removeHandler id' = P.atomicModify (removeEventHandler (Proxy @s) id')+ -- | Fire an event that the bot will then handle. -- -- ==== Examples@@ -159,6 +193,59 @@   inc <- P.asks (^. #eventsIn)   P.embed $ dupChan inc +-- | Wait until an event satisfying a condition happens, then returns it's+-- parameters+--+-- Sorry about this horrendous type sig, this is what it would look like with @s+-- ~ \''MessageCreateEvt'@:+--+-- @+-- 'waitUntil' :: ('Message' -> 'P.Sem' r 'Bool') -> 'P.Sem' r 'Message'+-- @+--+-- And for @s ~ \''MessageUpdateEvt'@:+--+-- @+-- 'waitUntil' :: ('Message' -> 'Message' -> 'P.Sem' r 'Bool') -> 'P.Sem' r ('Message', 'Message')+-- @+--+-- ==== Examples+--+-- Waiting for a message containing the text \"hi\":+--+-- @+-- f = do msg \<\- 'waitUntil' @\''MessageCreateEvt' (\m -> 'pure' $ 'Data.Text.Lazy.isInfixOf' "hi" $ m ^. #content)+--        print $ msg ^. #content+-- @+waitUntil+  :: forall (s :: EventType) r t eh ehB.+  ( BotC r+  , InsertEventHandler s+  , RemoveEventHandler s+  , Uncurry eh+  , eh ~ EHType s (P.Sem r) ()+  , eh ~ Curried (t -> P.Sem r ())+  , Uncurry ehB+  , Uncurried ehB ~ (t -> P.Sem r Bool)+  , Curry (t -> IO ())+  , Curried (t -> IO ()) ~ EHType s IO ()+  )+  => ehB+  -> P.Sem r t+waitUntil f = do+  result <- P.embed newEmptyMVar+  remove <- react @s (curryG $ checker result)+  res <- P.embed $ takeMVar result+  remove+  pure res+  where+    checker :: MVar t -> t -> P.Sem r ()+    checker result args = do+      res <- uncurryG f args+      debug $ "checker result: " +|| res ||+ ""+      when res $ do+        P.embed $ putMVar result args+ -- | Set the bot's presence on all shards. sendPresence :: BotC r => StatusUpdateData -> P.Sem r () sendPresence s = do@@ -170,9 +257,6 @@ stopBot :: BotC r => P.Sem r () stopBot = do   debug "stopping bot"-  shards <- P.asks (^. #shards) >>= P.embed . readTVarIO-  for_ shards $ \(inc, _) ->-    P.embed $ writeChan inc ShutDownShard   inc <- P.asks (^. #eventsIn)   P.embed $ writeChan inc ShutDown @@ -180,6 +264,8 @@ finishUp = do   debug "finishing up"   shards <- P.asks (^. #shards) >>= P.embed . readTVarIO+  for_ shards $ \(inc, _) ->+    P.embed $ writeChan inc ShutDownShard   for_ shards $ \(_, shardThread) -> P.await shardThread   debug "bot has stopped" @@ -204,8 +290,15 @@    let handlers = getCustomEventHandlers s (dynTypeRep d) eventHandlers -  for_ handlers (\h -> P.async . fromJust . fromDynamic @(P.Sem r ()) . fromJust $ dynApply h d)+  for_ handlers (\h -> P.async . P.embed $ h d) +catchAllLogging :: BotC r => P.Sem r () -> P.Sem r ()+catchAllLogging m = do+  r <- P.errorToIOFinal . P.fromExceptionSem @SomeException $ P.raise m+  case r of+    Right _ -> pure ()+    Left e -> debug $ "got exception: " +|| e ||+ ""+ handleEvent :: BotC r => DispatchData -> P.Sem r () handleEvent data' = do   debug "handling an event"@@ -220,7 +313,7 @@    case actions of     Right actions -> for_ actions $ \action -> P.async $ do-      (time, _) <- timeA $ Di.reset action+      (time, _) <- timeA . catchAllLogging $ P.embed action       void $ observeHistogram time eventHandleHisto     Left err      -> debug $ "Failed handling actions for event: " +| err |+ "" @@ -236,7 +329,7 @@ handleEvent' :: BotC r               => EventHandlers               -> DispatchData-              -> P.Sem (P.Fail ': r) [P.Sem r ()]+              -> P.Sem (P.Fail ': r) [IO ()] handleEvent' eh evt@(Ready rd@ReadyData {}) = do   updateCache evt   pure $ map ($ rd) (getEventHandlers @'ReadyEvt eh)
src/Calamity/Client/ShardManager.hs view
@@ -21,9 +21,13 @@ import qualified Polysemy                    as P import qualified Polysemy.Reader             as P +mapLeft :: (a -> c) -> Either a b -> Either c b+mapLeft f (Left a) = Left $ f a+mapLeft _ (Right b) = Right b+ -- | Connects the bot to the gateway over n shards-shardBot :: (BotC r, P.Member P.Fail r) => Sem r ()-shardBot = do+shardBot :: BotC r => Sem r (Either StartupError ())+shardBot = (mapLeft StartupError <$>) . P.runFail $ do   numShardsVar <- P.asks numShards   shardsVar <- P.asks shards 
src/Calamity/Client/Types.hs view
@@ -1,12 +1,14 @@ -- | Types for the client module Calamity.Client.Types     ( Client(..)+    , StartupError(..)     , EventType(..)     , EHType     , BotC     , SetupEff     , EventHandlers(..)     , InsertEventHandler(..)+    , RemoveEventHandler(..)     , getEventHandlers     , getCustomEventHandlers ) where @@ -29,8 +31,8 @@  import           Data.Default.Class import           Data.Dynamic-import           Data.Functor import qualified Data.HashMap.Lazy               as LH+import           Data.IORef import           Data.Maybe import           Data.Time import qualified Data.TypeRepMap                 as TM@@ -47,12 +49,14 @@ import qualified Polysemy.Reader                 as P  data Client = Client-  { shards        :: TVar [(InChan ControlMessage, Async (Maybe ()))]-  , numShards     :: MVar Int-  , token         :: Token-  , rlState       :: RateLimitState-  , eventsIn      :: InChan CalamityEvent-  , eventsOut     :: OutChan CalamityEvent+  { shards              :: TVar [(InChan ControlMessage, Async (Maybe ()))]+  , numShards           :: MVar Int+  , token               :: Token+  , rlState             :: RateLimitState+  , eventsIn            :: InChan CalamityEvent+  , eventsOut           :: OutChan CalamityEvent+  , ehidCounter         :: IORef Integer+  , originalEffectsType :: TypeRep   }   deriving ( Generic ) @@ -62,8 +66,11 @@   , Typeable r)  -- | A concrete effect stack used inside the bot-type SetupEff r = P.Sem (LogEff ': P.Reader Client ': P.AtomicState EventHandlers ': P.Async ': r) ()+type SetupEff r = (LogEff ': P.Reader Client ': P.AtomicState EventHandlers ': P.Async ': r) +newtype StartupError = StartupError String+  deriving ( Show )+ -- | A Data Kind used to fire custom events data EventType   = ReadyEvt@@ -99,75 +106,51 @@  -- | A type family to decide what the parameters for an event handler should be -- determined by the type of event it is handling.-type family EHType (d :: EventType) m where-  EHType 'ReadyEvt                    m = ReadyData                                   -> m ()-  EHType 'ChannelCreateEvt            m = Channel                                     -> m ()-  EHType 'ChannelUpdateEvt            m = Channel   -> Channel                        -> m ()-  EHType 'ChannelDeleteEvt            m = Channel                                     -> m ()-  EHType 'ChannelpinsUpdateEvt        m = Channel   -> Maybe UTCTime                  -> m ()-  EHType 'GuildCreateEvt              m = Guild     -> Bool                           -> m ()-  EHType 'GuildUpdateEvt              m = Guild     -> Guild                          -> m ()-  EHType 'GuildDeleteEvt              m = Guild     -> Bool                           -> m ()-  EHType 'GuildBanAddEvt              m = Guild     -> User                           -> m ()-  EHType 'GuildBanRemoveEvt           m = Guild     -> User                           -> m ()-  EHType 'GuildEmojisUpdateEvt        m = Guild     -> [Emoji]                        -> m ()-  EHType 'GuildIntegrationsUpdateEvt  m = Guild                                       -> m ()-  EHType 'GuildMemberAddEvt           m = Member                                      -> m ()-  EHType 'GuildMemberRemoveEvt        m = Member                                      -> m ()-  EHType 'GuildMemberUpdateEvt        m = Member    -> Member                         -> m ()-  EHType 'GuildMembersChunkEvt        m = Guild     -> [Member]                       -> m ()-  EHType 'GuildRoleCreateEvt          m = Guild     -> Role                           -> m ()-  EHType 'GuildRoleUpdateEvt          m = Guild     -> Role          -> Role          -> m ()-  EHType 'GuildRoleDeleteEvt          m = Guild     -> Role                           -> m ()-  EHType 'MessageCreateEvt            m = Message                                     -> m ()-  EHType 'MessageUpdateEvt            m = Message   -> Message                        -> m ()-  EHType 'MessageDeleteEvt            m = Message                                     -> m ()-  EHType 'MessageDeleteBulkEvt        m = [Message]                                   -> m ()-  EHType 'MessageReactionAddEvt       m = Message   -> Reaction                       -> m ()-  EHType 'MessageReactionRemoveEvt    m = Message   -> Reaction                       -> m ()-  EHType 'MessageReactionRemoveAllEvt m = Message                                     -> m ()-  EHType 'TypingStartEvt              m = Channel   -> Maybe Member  -> UnixTimestamp -> m ()-  EHType 'UserUpdateEvt               m = User      -> User                           -> m ()-  EHType ('CustomEvt s a)             m = a                                           -> m ()+type family EHType (d :: EventType) m r where+  EHType 'ReadyEvt                    m r = ReadyData                                   -> m r+  EHType 'ChannelCreateEvt            m r = Channel                                     -> m r+  EHType 'ChannelUpdateEvt            m r = Channel   -> Channel                        -> m r+  EHType 'ChannelDeleteEvt            m r = Channel                                     -> m r+  EHType 'ChannelpinsUpdateEvt        m r = Channel   -> Maybe UTCTime                  -> m r+  EHType 'GuildCreateEvt              m r = Guild     -> Bool                           -> m r+  EHType 'GuildUpdateEvt              m r = Guild     -> Guild                          -> m r+  EHType 'GuildDeleteEvt              m r = Guild     -> Bool                           -> m r+  EHType 'GuildBanAddEvt              m r = Guild     -> User                           -> m r+  EHType 'GuildBanRemoveEvt           m r = Guild     -> User                           -> m r+  EHType 'GuildEmojisUpdateEvt        m r = Guild     -> [Emoji]                        -> m r+  EHType 'GuildIntegrationsUpdateEvt  m r = Guild                                       -> m r+  EHType 'GuildMemberAddEvt           m r = Member                                      -> m r+  EHType 'GuildMemberRemoveEvt        m r = Member                                      -> m r+  EHType 'GuildMemberUpdateEvt        m r = Member    -> Member                         -> m r+  EHType 'GuildMembersChunkEvt        m r = Guild     -> [Member]                       -> m r+  EHType 'GuildRoleCreateEvt          m r = Guild     -> Role                           -> m r+  EHType 'GuildRoleUpdateEvt          m r = Guild     -> Role          -> Role          -> m r+  EHType 'GuildRoleDeleteEvt          m r = Guild     -> Role                           -> m r+  EHType 'MessageCreateEvt            m r = Message                                     -> m r+  EHType 'MessageUpdateEvt            m r = Message   -> Message                        -> m r+  EHType 'MessageDeleteEvt            m r = Message                                     -> m r+  EHType 'MessageDeleteBulkEvt        m r = [Message]                                   -> m r+  EHType 'MessageReactionAddEvt       m r = Message   -> Reaction                       -> m r+  EHType 'MessageReactionRemoveEvt    m r = Message   -> Reaction                       -> m r+  EHType 'MessageReactionRemoveAllEvt m r = Message                                     -> m r+  EHType 'TypingStartEvt              m r = Channel   -> Maybe Member  -> UnixTimestamp -> m r+  EHType 'UserUpdateEvt               m r = User      -> User                           -> m r+  EHType ('CustomEvt s a)             m r = a                                           -> m r -type family EHType' (d :: EventType) where-  EHType' 'ReadyEvt                    = Dynamic-  EHType' 'ChannelCreateEvt            = Dynamic-  EHType' 'ChannelUpdateEvt            = Dynamic-  EHType' 'ChannelDeleteEvt            = Dynamic-  EHType' 'ChannelpinsUpdateEvt        = Dynamic-  EHType' 'GuildCreateEvt              = Dynamic-  EHType' 'GuildUpdateEvt              = Dynamic-  EHType' 'GuildDeleteEvt              = Dynamic-  EHType' 'GuildBanAddEvt              = Dynamic-  EHType' 'GuildBanRemoveEvt           = Dynamic-  EHType' 'GuildEmojisUpdateEvt        = Dynamic-  EHType' 'GuildIntegrationsUpdateEvt  = Dynamic-  EHType' 'GuildMemberAddEvt           = Dynamic-  EHType' 'GuildMemberRemoveEvt        = Dynamic-  EHType' 'GuildMemberUpdateEvt        = Dynamic-  EHType' 'GuildMembersChunkEvt        = Dynamic-  EHType' 'GuildRoleCreateEvt          = Dynamic-  EHType' 'GuildRoleUpdateEvt          = Dynamic-  EHType' 'GuildRoleDeleteEvt          = Dynamic-  EHType' 'MessageCreateEvt            = Dynamic-  EHType' 'MessageUpdateEvt            = Dynamic-  EHType' 'MessageDeleteEvt            = Dynamic-  EHType' 'MessageDeleteBulkEvt        = Dynamic-  EHType' 'MessageReactionAddEvt       = Dynamic-  EHType' 'MessageReactionRemoveEvt    = Dynamic-  EHType' 'MessageReactionRemoveAllEvt = Dynamic-  EHType' 'TypingStartEvt              = Dynamic-  EHType' 'UserUpdateEvt               = Dynamic-  EHType' ('CustomEvt _ _)             = Dynamic+type StoredEHType t = EHType t IO ()  newtype EventHandlers = EventHandlers (TypeRepMap EventHandler) -type family EHStorageType t where-  EHStorageType ('CustomEvt s a) = LH.HashMap TypeRep (LH.HashMap TypeRep [Dynamic])-  EHStorageType t                = [EHType' t]+data EventHandlerWithID a = EventHandlerWithID+  { ehID :: Integer+  , eh   :: a+  } -newtype EventHandler t = EH+type family EHStorageType (t :: EventType) where+  EHStorageType ('CustomEvt s a) = LH.HashMap TypeRep (LH.HashMap TypeRep [EventHandlerWithID (StoredEHType ('CustomEvt s a))])+  EHStorageType t                = [EventHandlerWithID (StoredEHType t)]++newtype EventHandler (t :: EventType) = EH   { unwrapEventHandler :: (Semigroup (EHStorageType t), Monoid (EHStorageType t)) => EHStorageType t   } @@ -206,7 +189,7 @@                                  , WrapTypeable $ EH @'MessageReactionRemoveAllEvt []                                  , WrapTypeable $ EH @'TypingStartEvt []                                  , WrapTypeable $ EH @'UserUpdateEvt []-                                 , WrapTypeable $ EH @('CustomEvt Void Void) LH.empty+                                 , WrapTypeable $ EH @('CustomEvt Void Dynamic) LH.empty                                  ]  instance Semigroup EventHandlers where@@ -221,50 +204,79 @@   EHInstanceSelector ('CustomEvt _ _) = 'True   EHInstanceSelector _                = 'False ++fromDynamicJust :: forall a. Typeable a => Dynamic -> a+fromDynamicJust d = case fromDynamic d of+  Just x -> x+  Nothing -> error $ "Extracting dynamic failed, wanted: " <> (show . typeRep $ Proxy @a) <> ", got: " <> (show $ dynTypeRep d)++ -- | A helper typeclass that is used to decide how to register regular -- events, and custom events which require storing in a map at runtime.-class InsertEventHandler a m where-  makeEventHandlers :: Proxy a -> Proxy m -> EHType a m -> EventHandlers+class InsertEventHandler a where+  makeEventHandlers :: Proxy a -> Integer -> StoredEHType a -> EventHandlers -instance (EHInstanceSelector a ~ flag, InsertEventHandler' flag a m) => InsertEventHandler a m where+instance (EHInstanceSelector a ~ flag, InsertEventHandler' flag a) => InsertEventHandler a where   makeEventHandlers = makeEventHandlers' (Proxy @flag) -class InsertEventHandler' (flag :: Bool) a m where-  makeEventHandlers' :: Proxy flag -> Proxy a -> Proxy m -> EHType a m -> EventHandlers+class InsertEventHandler' (flag :: Bool) a where+  makeEventHandlers' :: Proxy flag -> Proxy a -> Integer -> StoredEHType a -> EventHandlers -instance (Typeable a, Typeable s, Typeable (EHType ('CustomEvt s a) m))-  => InsertEventHandler' 'True ('CustomEvt s a) m where-  makeEventHandlers' _ _ _ handler = EventHandlers . TM.one $ EH @('CustomEvt Void Void)-    (LH.singleton (typeRep $ Proxy @s) (LH.singleton (typeRep $ Proxy @a) [toDyn handler]))+intoDynFn :: forall a. Typeable a => (a -> IO ()) -> (Dynamic -> IO ())+intoDynFn fn = \d -> fn $ fromDynamicJust d -instance (Typeable s, EHStorageType s ~ [Dynamic], Typeable (EHType s m)) => InsertEventHandler' 'False s m where-  makeEventHandlers' _ _ _ handler = EventHandlers . TM.one $ EH @s [toDyn handler]+instance (Typeable a, Typeable s, Typeable (StoredEHType ('CustomEvt s a)), EHType ('CustomEvt s a) IO () ~ (a -> IO ()))+  => InsertEventHandler' 'True ('CustomEvt s a) where+  makeEventHandlers' _ _ id' handler = EventHandlers . TM.one $ EH @('CustomEvt Void Dynamic)+    (LH.singleton (typeRep $ Proxy @s) (LH.singleton (typeRep $ Proxy @a) [EventHandlerWithID id' (intoDynFn handler)])) +instance (Typeable s, EHStorageType s ~ [EventHandlerWithID (StoredEHType s)], Typeable (StoredEHType s)) => InsertEventHandler' 'False s where+  makeEventHandlers' _ _ id' handler = EventHandlers . TM.one $ EH @s [EventHandlerWithID id' handler] -class GetEventHandlers a m where-  getEventHandlers :: EventHandlers -> [EHType a m] -instance (EHInstanceSelector a ~ flag, GetEventHandlers' flag a m) => GetEventHandlers a m where-  getEventHandlers = getEventHandlers' (Proxy @a) (Proxy @m) (Proxy @flag)+class GetEventHandlers a where+  getEventHandlers :: EventHandlers -> [StoredEHType a] -class GetEventHandlers' (flag :: Bool) a m where-  getEventHandlers' :: Proxy a -> Proxy m -> Proxy flag -> EventHandlers -> [EHType a m]+instance (EHInstanceSelector a ~ flag, GetEventHandlers' flag a) => GetEventHandlers a where+  getEventHandlers = getEventHandlers' (Proxy @a) (Proxy @flag) -instance (Typeable a, Typeable s, Typeable (EHType ('CustomEvt s a) m)) => GetEventHandlers' 'True ('CustomEvt s a) m where-  getEventHandlers' _ _ _ (EventHandlers handlers) =-    let handlerMap = unwrapEventHandler @('CustomEvt Void Void) $ fromJust-          (TM.lookup handlers :: Maybe (EventHandler ('CustomEvt Void Void)))-    in concat $ LH.lookup (typeRep $ Proxy @s) handlerMap >>= LH.lookup (typeRep $ Proxy @a) <&> map-       (fromJust . fromDynamic)+class GetEventHandlers' (flag :: Bool) a where+  getEventHandlers' :: Proxy a -> Proxy flag -> EventHandlers -> [StoredEHType a] -instance (Typeable s, Typeable (EHType s m), EHStorageType s ~ [Dynamic]) => GetEventHandlers' 'False s m where-  getEventHandlers' _ _ _ (EventHandlers handlers) =+instance GetEventHandlers' 'True ('CustomEvt s a) where+  getEventHandlers' _ _ _ = error "use getCustomEventHandlers instead"+    -- let handlerMap = unwrapEventHandler @('CustomEvt Void Dynamic) $ fromJust+    --       (TM.lookup handlers :: Maybe (EventHandler ('CustomEvt Void Dynamic)))+    -- in concat $ LH.lookup (typeRep $ Proxy @s) handlerMap >>= LH.lookup (typeRep $ Proxy @a) <&> map eh++instance (Typeable s, Typeable (StoredEHType s), EHStorageType s ~ [EventHandlerWithID (StoredEHType s)]) => GetEventHandlers' 'False s where+  getEventHandlers' _ _ (EventHandlers handlers) =     let theseHandlers = unwrapEventHandler @s $ fromJust (TM.lookup handlers :: Maybe (EventHandler s))-    in map (fromJust . fromDynamic) theseHandlers+    in map eh theseHandlers  -getCustomEventHandlers :: TypeRep -> TypeRep -> EventHandlers -> [Dynamic]+class RemoveEventHandler a where+  removeEventHandler :: Proxy a -> Integer -> EventHandlers -> EventHandlers++instance (EHInstanceSelector a ~ flag, RemoveEventHandler' flag a) => RemoveEventHandler a where+  removeEventHandler = removeEventHandler' (Proxy @flag)++class RemoveEventHandler' (flag :: Bool) a where+  removeEventHandler' :: Proxy flag -> Proxy a -> Integer -> EventHandlers -> EventHandlers++instance (Typeable s, Typeable a) => RemoveEventHandler' 'True ('CustomEvt s a) where+  removeEventHandler' _ _ id' (EventHandlers handlers) = EventHandlers $ TM.adjust @('CustomEvt Void Dynamic)+    (\(EH ehs) -> EH (LH.update (Just . LH.update (Just . filter ((/= id') . ehID)) (typeRep $ Proxy @a))+                      (typeRep $ Proxy @s) ehs)) handlers++instance (Typeable s, Typeable (StoredEHType s), EHStorageType s ~ [EventHandlerWithID (StoredEHType s)])+  => RemoveEventHandler' 'False s where+  removeEventHandler' _ _ id' (EventHandlers handlers) = EventHandlers $ TM.adjust @s+    (\(EH ehs) -> EH $ filter ((/= id') . ehID) ehs) handlers+++getCustomEventHandlers :: TypeRep -> TypeRep -> EventHandlers -> [Dynamic -> IO ()] getCustomEventHandlers s a (EventHandlers handlers) =-    let handlerMap = unwrapEventHandler @('CustomEvt Void Void) $ fromJust-          (TM.lookup handlers :: Maybe (EventHandler ('CustomEvt Void Void)))-    in concat $ LH.lookup s handlerMap >>= LH.lookup a+    let handlerMap = unwrapEventHandler @('CustomEvt Void Dynamic) $ fromJust+          (TM.lookup handlers :: Maybe (EventHandler ('CustomEvt Void Dynamic)))+    in map eh . concat $ LH.lookup s handlerMap >>= LH.lookup a
+ src/Calamity/Internal/GenericCurry.hs view
@@ -0,0 +1,115 @@+-- | Generic arity curry/ uncurry+module Calamity.Internal.GenericCurry+    ( Curry(..)+    , Uncurry(..) ) where++import           Data.Typeable++import           GHC.TypeNats++class Curry t where+  type Curried t+  type Parameters t++  curryG :: t -> Curried t++type family CurryInstanceSelector t :: Nat where+  CurryInstanceSelector (a -> b -> c -> d -> e -> f -> r) = 6+  CurryInstanceSelector (a -> b -> c -> d -> e -> r) = 5+  CurryInstanceSelector (a -> b -> c -> d -> r) = 4+  CurryInstanceSelector (a -> b -> c -> r) = 3+  CurryInstanceSelector (a -> b -> r) = 2+  CurryInstanceSelector (a -> r) = 1++class Curry' (flag :: Nat) t where+  type Curried' (flag :: Nat) t+  type Parameters' (flag :: Nat) t++  curryG' :: Proxy flag -> t -> Curried' flag t++instance (CurryInstanceSelector t ~ flag, Curry' flag t) => Curry t where+  type Curried t = Curried' (CurryInstanceSelector t) t+  type Parameters t = Parameters' (CurryInstanceSelector t) t++  curryG = curryG' (Proxy @flag)++instance Curry' 6 ((a, b, c, d, e, f) -> r) where+  type Curried' 6 ((a, b, c, d, e, f) -> r) = a -> b -> c -> d -> e -> f -> r+  type Parameters' 6 ((a, b, c, d, e, f) -> r) = (a, b, c, d, e, f)++  curryG' _ fn a b c d e f = fn (a, b, c, d, e, f)++instance Curry' 5 ((a, b, c, d, e) -> r) where+  type Curried' 5 ((a, b, c, d, e) -> r) = a -> b -> c -> d -> e -> r+  type Parameters' 5 ((a, b, c, d, e) -> r) = (a, b, c, d, e)++  curryG' _ fn a b c d e = fn (a, b, c, d, e)++instance Curry' 4 ((a, b, c, d) -> r) where+  type Curried' 4 ((a, b, c, d) -> r) = a -> b -> c -> d -> r+  type Parameters' 4 ((a, b, c, d) -> r) = (a, b, c, d)++  curryG' _ fn a b c d = fn (a, b, c, d)++instance Curry' 3 ((a, b, c) -> r) where+  type Curried' 3 ((a, b, c) -> r) = a -> b -> c -> r+  type Parameters' 3 ((a, b, c) -> r) = (a, b, c)++  curryG' _ fn a b c = fn (a, b, c)++instance Curry' 2 ((a, b) -> r) where+  type Curried' 2 ((a, b) -> r) = a -> b -> r+  type Parameters' 2 ((a, b) -> r) = (a, b)++  curryG' _ fn a b = fn (a, b)++instance Curry' 1 (a -> r) where+  type Curried' 1 (a -> r) = a -> r+  type Parameters' 1 (a -> r) = a++  curryG' _ fn = fn++class Uncurry t where+  type Uncurried t++  uncurryG :: t -> Uncurried t++class Uncurry' (flag :: Nat) t where+  type Uncurried' (flag :: Nat) t++  uncurryG' :: Proxy flag -> t -> Uncurried' flag t++instance (CurryInstanceSelector t ~ flag, Uncurry' flag t) => Uncurry t where+  type Uncurried t = Uncurried' (CurryInstanceSelector t) t++  uncurryG = uncurryG' (Proxy @flag)++instance Uncurry' 6 (a -> b -> c -> d -> e -> f -> r) where+  type Uncurried' 6 (a -> b -> c -> d -> e -> f -> r) = (a, b, c, d, e, f) -> r++  uncurryG' _ fn (a, b, c, d, e, f) = fn a b c d e f++instance Uncurry' 5 (a -> b -> c -> d -> e -> r) where+  type Uncurried' 5 (a -> b -> c -> d -> e -> r) = (a, b, c, d, e) -> r++  uncurryG' _ f (a, b, c, d, e) = f a b c d e++instance Uncurry' 4 (a -> b -> c -> d -> r) where+  type Uncurried' 4 (a -> b -> c -> d -> r) = (a, b, c, d) -> r++  uncurryG' _ f (a, b, c, d) = f a b c d++instance Uncurry' 3 (a -> b -> c -> r) where+  type Uncurried' 3 (a -> b -> c -> r) = (a, b, c) -> r++  uncurryG' _ f (a, b, c) = f a b c++instance Uncurry' 2 (a -> b -> r) where+  type Uncurried' 2 (a -> b -> r) = (a, b) -> r++  uncurryG' _ f (a, b) = f a b++instance Uncurry' 1 (a -> r) where+  type Uncurried' 1 (a -> r) = a -> r++  uncurryG' _ f = f
+ src/Calamity/Internal/RunIntoIO.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE TemplateHaskell #-}++-- | Something for converting polysemy actions into IO actions+module Calamity.Internal.RunIntoIO+    ( IntoIO(..)+    , runIntoIOFinal+    , intoIO ) where++import           Control.Monad++import           Data.Functor++import qualified Polysemy                         as P+import qualified Polysemy.Final                   as P++data IntoIO p m a where+  IntoIO :: (p -> m ()) -> IntoIO p m (p -> IO ())++runIntoIOFinal :: forall r p a. P.Member (P.Final IO) r => P.Sem (IntoIO p ': r) a -> P.Sem r a+runIntoIOFinal = P.interpretFinal $ \case+  IntoIO m -> do+    istate <- P.getInitialStateS+    m' <- P.bindS m+    P.liftS $ pure (\x -> void (m' $ istate $> x))++P.makeSem ''IntoIO