packages feed

monad-effect 0.1.0.0 → 0.2.0.0

raw patch · 15 files changed

+602/−202 lines, 15 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Monad.Effect: instance (GHC.Internal.Base.Monad m, Data.TypeList.ConsFData.ConsFDataList c mods, Data.TypeList.InList Control.Monad.Effect.MonadThrowError es) => Control.Monad.Catch.MonadCatch (Control.Monad.Effect.EffT' c mods es m)
- Control.Monad.Effect: instance (GHC.Internal.Base.Monad m, Data.TypeList.ConsFData.ConsFDataList c mods, Data.TypeList.InList Control.Monad.Effect.MonadThrowError es) => Control.Monad.Catch.MonadThrow (Control.Monad.Effect.EffT' c mods es m)
- Control.System: class Loadable c mod mods => LoadableArgs (c :: Type -> Type -> [Type] -> Type) mod (mods :: [Type])
- Control.System: class Loadable c mod mods => LoadableEnv (c :: Type -> Type -> [Type] -> Type) mod (mods :: [Type])
- Control.System: class System (c :: Type -> Type -> [Type] -> Type) (mods :: [Type])
- Control.System: class System c mods => SystemArgs (c :: Type -> Type -> [Type] -> Type) (mods :: [Type])
- Control.System: class System c mods => SystemEnv (c :: Type -> Type -> [Type] -> Type) (mods :: [Type])
- Control.System: data family ModuleInitDataHardCode mod
- Control.System: initAllModules :: System c mods => SystemInitData c mods -> EffT' c ('[] :: [Type]) '[SystemError] IO (SystemRead c mods, SystemState c mods)
- Control.System: initModule :: Loadable c mod mods => ModuleInitData mod -> EffT' c mods '[SystemError] IO (ModuleRead mod, ModuleState mod)
- Control.System: instance (Control.Monad.Effect.SystemModule mod, Control.System.System c mods, Control.System.Loadable c mod mods) => Control.System.System c (mod : mods)
- Control.System: instance (Data.TypeList.SubList c mods (mod : mods), Control.Monad.Effect.SystemModule mod, Control.System.SystemArgs c mods, Control.System.Loadable c mod mods, Control.System.LoadableArgs c mod mods) => Control.System.SystemArgs c (mod : mods)
- Control.System: instance (Data.TypeList.SubList c mods (mod : mods), Control.Monad.Effect.SystemModule mod, Control.System.SystemEnv c mods, Control.System.Loadable c mod mods, Control.System.LoadableEnv c mod mods) => Control.System.SystemEnv c (mod : mods)
- Control.System: instance Control.System.System c '[]
- Control.System: instance Control.System.SystemArgs c '[]
- Control.System: instance Control.System.SystemEnv c '[]
- Control.System: readInitDataFromArgs :: LoadableArgs c mod mods => ModuleInitDataHardCode mod -> [String] -> EffT' c ('[] :: [Type]) '[SystemError] IO (ModuleInitData mod)
- Control.System: readInitDataFromEnv :: LoadableEnv c mod mods => ModuleInitDataHardCode mod -> EffT' c ('[] :: [Type]) '[SystemError] IO (ModuleInitData mod)
- Control.System: readSystemInitDataFromArgs :: SystemArgs c mods => SystemInitDataHardCode' c mods -> [String] -> EffT' c ('[] :: [Type]) '[SystemError] IO (SystemInitData c mods)
- Control.System: readSystemInitDataFromEnv :: SystemEnv c mods => SystemInitDataHardCode' c mods -> EffT' c ('[] :: [Type]) '[SystemError] IO (SystemInitData c mods)
- Control.System: releaseModule :: Loadable c mod mods => EffT' c (mod ': mods) (NoError :: [Type]) IO ()
- Control.System: releaseSystem :: System c mods => EffT' c mods ('[] :: [Type]) IO ()
- Control.System: runSystemWithInitData :: forall (mods :: [Type]) (es :: [Type]) m c a. (ConsFDataList c mods, System c mods, MonadIO m) => SystemInitData c mods -> EffT' c mods es m a -> m (Either SystemError (Result es a, SystemState c mods))
- Control.System: type SystemInitDataHardCode (mods :: [Type]) = SystemInitDataHardCode' FData :: Type -> Type -> [Type] -> Type mods
- Control.System: type SystemInitDataHardCode' (c :: Type -> Type -> k1 -> k) (mods :: k1) = c ModuleInitDataHardCode mods
- Control.System: type SystemInitDataHardCodeL (mods :: [Type]) = SystemInitDataHardCode' FList mods
- Control.System.EventLoop: eventLoopWithRelease :: forall (mods :: [Type]). (ConsFDataList (FData :: (Type -> Type) -> [Type] -> Type) mods, System (FData :: (Type -> Type) -> [Type] -> Type) mods) => Eff mods (NoError :: [Type]) ()
- Control.System.EventLoop: eventLoopWithReleaseRestartIO :: forall (mods :: [Type]). (ConsFDataList (FData :: (Type -> Type) -> [Type] -> Type) mods, System (FData :: (Type -> Type) -> [Type] -> Type) mods) => SystemInitData (FData :: (Type -> Type) -> [Type] -> Type) mods -> IO ()
- Module.Resource: instance Control.System.Loadable c Module.Resource.Resource mods
+ Control.Monad.Effect: MonadFailError :: String -> MonadFailError
+ Control.Monad.Effect: baseTransform :: forall m n (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) b. (forall a. () => m a -> n a) -> EffT' c mods es m b -> EffT' c mods es n b
+ Control.Monad.Effect: bracketEffT :: forall (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) a b. (MonadMask m, HasCallStack) => EffT' c mods es m a -> (a -> EffT' c mods es m ()) -> (a -> EffT' c mods es m b) -> EffT' c mods es m b
+ Control.Monad.Effect: class MonadCatch m => MonadMask (m :: Type -> Type)
+ Control.Monad.Effect: effThrowEList :: forall (es :: [Type]) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (m :: Type -> Type) a. Monad m => EList es -> EffT' c mods es m a
+ Control.Monad.Effect: effThrowEListIn :: forall (es :: [Type]) (es' :: [Type]) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (m :: Type -> Type) a. (Monad m, NonEmptySubList es es') => EList es -> EffT' c mods es' m a
+ Control.Monad.Effect: effTry :: forall e (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) a. (Exception e, MonadCatch m) => EffT' c mods es m a -> EffT' c mods (e ': es) m a
+ Control.Monad.Effect: effTryIn :: forall e (es :: [Type]) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (m :: Type -> Type) a. (Exception e, MonadCatch m, InList e es) => EffT' c mods es m a -> EffT' c mods es m a
+ Control.Monad.Effect: effTryInWith :: forall e e' (es :: [Type]) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (m :: Type -> Type) a. (Exception e, MonadCatch m, InList e' es) => (e -> e') -> EffT' c mods es m a -> EffT' c mods es m a
+ Control.Monad.Effect: effTryWith :: forall e e' (es :: [Type]) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (m :: Type -> Type) a. (Exception e, MonadCatch m) => (e -> e') -> EffT' c mods es m a -> EffT' c mods (e' ': es) m a
+ Control.Monad.Effect: embedNoError :: forall (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) (m :: Type -> Type) a. Monad m => EffT' c mods (NoError :: [Type]) m a -> EffT' c mods es m a
+ Control.Monad.Effect: errorInToEither :: forall e (es :: [Type]) (mods :: [Type]) (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) a. (Monad m, InList e es) => EffT' c mods es m a -> EffT' c mods (Remove (FirstIndex e es) es) m (Either e a)
+ Control.Monad.Effect: errorInToMaybe :: forall e (es :: [Type]) (mods :: [Type]) (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) a. (Monad m, InList e es) => EffT' c mods es m a -> EffT' c mods (Remove (FirstIndex e es) es) m (Maybe a)
+ Control.Monad.Effect: errorToMaybe :: forall (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) e (es :: [Type]) a. Monad m => EffT' c mods (e ': es) m a -> EffT' c mods es m (Maybe a)
+ Control.Monad.Effect: errorToResult :: forall (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) a. Monad m => EffT' c mods es m a -> EffT' c mods (NoError :: [Type]) m (Result es a)
+ Control.Monad.Effect: foreverEffT :: forall (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) a never_returns. Monad m => EffT' c mods es m a -> EffT' c mods es m never_returns
+ Control.Monad.Effect: forkEffTFinally :: forall c (mods :: [Type]) (es :: [Type]) (noError :: [Type]) (m :: Type -> Type) a. (MonadIO m, MonadBaseControl IO m, MonadMask m, SubListEmbed es (AddIfNotElem SomeAsyncException es), InList SomeAsyncException (AddIfNotElem SomeAsyncException es)) => EffT' c mods es m a -> ((Result (AddIfNotElem SomeAsyncException es) a, SystemState c mods) -> EffT' c mods (NoError :: [Type]) m ()) -> EffT' c mods noError m ThreadId
+ Control.Monad.Effect: generalBracketEffT :: forall (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) a (es' :: [Type]) b o. (MonadMask m, HasCallStack) => EffT' c mods es m a -> (a -> Result es' b -> EffT' c mods es m o) -> (a -> EffT' c mods es' m b) -> EffT' c mods es m o
+ Control.Monad.Effect: instance (GHC.Internal.Base.Monad m, Data.TypeList.InList Control.Monad.Effect.MonadFailError es) => GHC.Internal.Control.Monad.Fail.MonadFail (Control.Monad.Effect.EffT' c mods es m)
+ Control.Monad.Effect: instance (GHC.Internal.Base.Monad m, Data.TypeList.InList Control.Monad.Effect.MonadThrowError es) => Control.Monad.Catch.MonadCatch (Control.Monad.Effect.EffT' c mods es m)
+ Control.Monad.Effect: instance (GHC.Internal.Base.Monad m, Data.TypeList.InList Control.Monad.Effect.MonadThrowError es) => Control.Monad.Catch.MonadThrow (Control.Monad.Effect.EffT' c mods es m)
+ Control.Monad.Effect: instance GHC.Internal.Base.Monad m => Control.Monad.RS.Class.MonadReadOnly (Control.Monad.Effect.SystemRead c mods) (Control.Monad.Effect.EffT' c mods es m)
+ Control.Monad.Effect: instance GHC.Internal.Show.Show Control.Monad.Effect.MonadFailError
+ Control.Monad.Effect: mapError :: forall (m :: Type -> Type) e1 e2 (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) a. Monad m => (e1 -> e2) -> EffT' c mods (e1 ': es) m a -> EffT' c mods (e2 ': es) m a
+ Control.Monad.Effect: maskEffT :: forall (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) (m :: Type -> Type) b. (MonadMask m, HasCallStack) => ((forall (c' :: (Type -> Type) -> [Type] -> Type) (mods' :: [Type]) (es' :: [Type]) a. () => EffT' c' mods' es' m a -> EffT' c' mods' es' m a) -> EffT' c mods es m b) -> EffT' c mods es m b
+ Control.Monad.Effect: newtype MonadFailError
+ Control.Monad.Effect: replaceEffTIn :: forall mod mod' (mods :: [Type]) (mods' :: [Type]) (es :: [Type]) (m :: Type -> Type) (c :: (Type -> Type) -> [Type] -> Type) a. (ReplaceElem c mods, mods' ~ Replace (FirstIndex mod mods) mod' mods, Monad m, In' c mod mods) => (ModuleRead mod -> ModuleState mod -> (ModuleRead mod', ModuleState mod')) -> (ModuleRead mod -> ModuleState mod -> ModuleState mod' -> ModuleState mod) -> EffT' c mods' es m a -> EffT' c mods es m a
+ Control.Monad.Effect: restoreAsync :: forall (m :: Type -> Type) (es :: [Type]) a (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]). (MonadIO m, MonadBaseControl IO m) => Async (StM m (Result es a, SystemState c mods)) -> EffT' c mods es m a
+ Control.Monad.Effect: restoreAsync_ :: forall (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) (m :: Type -> Type) a. (MonadIO m, MonadBaseControl IO m) => Async (StM m (Result es a, SystemState c mods)) -> EffT' c mods es m a
+ Control.Monad.RS.Class: class Monad m => MonadReadOnly r (m :: Type -> Type)
+ Control.Monad.RS.Class: instance (Control.Monad.Trans.Class.MonadTrans t, Control.Monad.RS.Class.MonadReadOnly r m) => Control.Monad.RS.Class.MonadReadOnly r (t m)
+ Control.Monad.RS.Class: instance (Control.Monad.Trans.Class.MonadTrans t, Control.Monad.RS.Class.MonadStateful s m) => Control.Monad.RS.Class.MonadStateful s (t m)
+ Control.System: class EventLoop (c :: Type -> Type -> [Type] -> Type) mod (mods :: [Type]) (es :: [Type])
+ Control.System: class EventLoopSystem (c :: Type -> Type -> [Type] -> Type) (mods :: [Type]) (es :: [Type])
+ Control.System: class WithSystem (c :: Type -> Type -> [Type] -> Type) (mods :: [Type]) (initEs :: [Type])
+ Control.System: detectAllFlags :: String -> (String -> Either Text a) -> [String] -> [Either Text a]
+ Control.System: detectFlag :: String -> (String -> Either Text a) -> [String] -> Maybe (Either Text a)
+ Control.System: instance (Control.Monad.Effect.SystemModule mod, Control.System.EventLoop c mod mods es, Control.System.EventLoopSystem c mods es) => Control.System.EventLoopSystem c (mod : mods) es
+ Control.System: instance (Control.Monad.Effect.SystemModule mod, Control.System.WithSystem c mods ies, Control.System.Loadable c mod mods ies) => Control.System.WithSystem c (mod : mods) ies
+ Control.System: instance Control.System.EventLoopSystem c '[] es
+ Control.System: instance Control.System.WithSystem c '[] ies
+ Control.System: withModule :: (Loadable c mod mods ies, ConsFDataList c (mod ': mods)) => ModuleInitData mod -> EffT' c (mod ': mods) ies IO a -> EffT' c mods ies IO a
+ Control.System: withSystem :: (WithSystem c mods initEs, ConsFDataList c mods) => SystemInitData c mods -> EffT' c mods initEs IO a -> EffT' c ('[] :: [Type]) initEs IO a
+ Data.TypeList: ($dmlensIn) :: (In' flist e es, ConsFData flist) => forall (fun :: Type -> Type). Functor fun => (f e -> fun (f e)) -> flist f es -> fun (flist f es)
+ Data.TypeList: class NonEmptySubList (ys :: [Type]) (xs :: [Type])
+ Data.TypeList: class When NonEmpty Tail ts ReplaceElem flist Tail ts => ReplaceElem (flist :: Type -> Type -> [Type] -> Type) (ts :: [Type])
+ Data.TypeList: instance (Data.TypeList.InList y xs, Data.TypeList.NonEmptySubList ys xs) => Data.TypeList.NonEmptySubList (y : ys) xs
+ Data.TypeList: instance Data.TypeList.NonEmptySubList '[x] (x : xs)
+ Data.TypeList: lensIn :: forall f fun. (In' flist e es, Functor fun) => (f e -> fun (f e)) -> flist f es -> fun (flist f es)
+ Data.TypeList: lensInS :: forall f fun t (ts :: [Type]). (ConsFData flist, Functor fun) => SFirstIndex t ts -> (f t -> fun (f t)) -> flist f ts -> fun (flist f ts)
+ Data.TypeList: replaceElem :: ReplaceElem flist ts => SFirstIndex t ts -> f t' -> flist f ts -> flist f (Replace (FirstIndex t ts) t' ts)
+ Data.TypeList: subListEListEmbed :: NonEmptySubList ys xs => EList ys -> EList xs
+ Data.TypeList: unReplaceElem :: ReplaceElem flist ts => SFirstIndex t ts -> Proxy t' -> (f t' -> f t) -> flist f (Replace (FirstIndex t ts) t' ts) -> flist f ts
+ Data.TypeList.FData: lensFDataByIndex :: FDataByIndex n ts => Proxy n -> forall (fun :: Type -> Type). Functor fun => (f (AtIndex ts n) -> fun (f (AtIndex ts n))) -> FData f ts -> fun (FData f ts)
+ Module.RS: instance (GHC.Internal.Base.Monad m, Data.TypeList.In' c (Module.RS.RModule r) mods) => Control.Monad.RS.Class.MonadReadOnly r (Control.Monad.Effect.EffT' c mods errs m)
+ Module.RS: instance (GHC.Internal.Base.Monad m, Data.TypeList.In' c (Module.RS.RModule r) mods) => Control.Monad.RS.Class.MonadReadable r (Control.Monad.Effect.EffT' c mods errs m)
+ Module.RS: instance (GHC.Internal.Base.Monad m, Data.TypeList.In' c (Module.RS.SModule s) mods) => Control.Monad.RS.Class.MonadStateful s (Control.Monad.Effect.EffT' c mods errs m)
+ Module.RS: instance Control.System.EventLoop c (Module.RS.RModule r) mods es
+ Module.RS: instance Control.System.EventLoop c (Module.RS.SModule s) mods es
+ Module.RS: instance Control.System.Loadable c (Module.RS.RModule r) mods ies
+ Module.RS: instance Control.System.Loadable c (Module.RS.SModule s) mods ies
+ Module.RS: readOnly :: forall s (mods :: [Type]) (errs :: [Type]) (m :: Type -> Type) a (c :: (Type -> Type) -> [Type] -> Type). (In' c (SModule s) (SModule s ': mods), ConsFDataList c (SModule s ': mods), ConsFDataList c (RModule s ': mods), Monad m) => EffT' c (RModule s ': mods) errs m a -> EffT' c (SModule s ': mods) errs m a
+ Module.RS.QQ: instance GHC.Internal.Show.Show Module.RS.QQ.DataFieldSpec
+ Module.Resource: instance Data.TypeList.ConsFData.ConsFDataList c (Module.Resource.Resource : mods) => Control.System.Loadable c Module.Resource.Resource mods es
- Control.Monad.Effect: asyncEffT :: forall (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) (m :: Type -> Type) a. (MonadIO m, MonadBaseControl IO m) => EffT' c mods es m a -> EffT' c mods (NoError :: [Type]) m (Async (StM m (Result es a, SystemState c mods)))
+ Control.Monad.Effect: asyncEffT :: forall (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) (m :: Type -> Type) a. MonadBaseControl IO m => EffT' c mods es m a -> EffT' c mods (NoError :: [Type]) m (Async (StM m (Result es a, SystemState c mods)))
- Control.Monad.Effect: effThrow :: forall (m :: Type -> Type) e (es :: [Type]) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) a. (Monad m, InList e es) => e -> EffT' c mods es m a
+ Control.Monad.Effect: effThrow :: forall e (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) (m :: Type -> Type) a. (Monad m, InList e es) => e -> EffT' c mods es m a
- Control.Monad.Effect: effThrowIn :: forall (m :: Type -> Type) e (es :: [Type]) (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) a. (Monad m, InList e es) => e -> EffT' c mods es m a
+ Control.Monad.Effect: effThrowIn :: forall e (c :: (Type -> Type) -> [Type] -> Type) (mods :: [Type]) (es :: [Type]) (m :: Type -> Type) a. (Monad m, InList e es) => e -> EffT' c mods es m a
- Control.Monad.RS.Class: class Monad m => MonadReadable r (m :: Type -> Type)
+ Control.Monad.RS.Class: class MonadReadOnly r m => MonadReadable r (m :: Type -> Type)
- Control.Monad.RS.Class: queries :: MonadReadable r m => (r -> r') -> m r'
+ Control.Monad.RS.Class: queries :: MonadReadOnly r m => (r -> r') -> m r'
- Control.Monad.RS.Class: query :: MonadReadable r m => m r
+ Control.Monad.RS.Class: query :: MonadReadOnly r m => m r
- Control.System: afterEvent :: Loadable c mod mods => EffT' c (mod ': mods) (NoError :: [Type]) IO ()
+ Control.System: afterEvent :: EventLoop c mod mods es => EffT' c (mod ': mods) es IO ()
- Control.System: afterSystem :: System c mods => EffT' c mods ('[] :: [Type]) IO ()
+ Control.System: afterSystem :: EventLoopSystem c mods es => EffT' c mods es IO ()
- Control.System: beforeEvent :: Loadable c mod mods => EffT' c (mod ': mods) (NoError :: [Type]) IO ()
+ Control.System: beforeEvent :: EventLoop c mod mods es => EffT' c (mod ': mods) es IO ()
- Control.System: beforeSystem :: System c mods => EffT' c mods ('[] :: [Type]) IO ()
+ Control.System: beforeSystem :: EventLoopSystem c mods es => EffT' c mods es IO ()
- Control.System: class Loadable (c :: Type -> Type -> [Type] -> Type) mod (mods :: [Type])
+ Control.System: class Loadable (c :: Type -> Type -> [Type] -> Type) mod (mods :: [Type]) (ies :: [Type])
- Control.System: handleEvent :: Loadable c mod mods => ModuleEvent mod -> EffT' c (mod ': mods) (NoError :: [Type]) IO ()
+ Control.System: handleEvent :: EventLoop c mod mods es => ModuleEvent mod -> EffT' c (mod ': mods) es IO ()
- Control.System: handleEvents :: System c mods => SystemEvent mods -> EffT' c mods ('[] :: [Type]) IO ()
+ Control.System: handleEvents :: EventLoopSystem c mods es => SystemEvent mods -> EffT' c mods es IO ()
- Control.System: listenToEvents :: System c mods => EffT' c mods ('[] :: [Type]) IO (STM (SystemEvent mods))
+ Control.System: listenToEvents :: EventLoopSystem c mods es => EffT' c mods es IO (STM (SystemEvent mods))
- Control.System: moduleEvent :: Loadable c mod mods => EffT' c (mod ': mods) (NoError :: [Type]) IO (STM (ModuleEvent mod))
+ Control.System: moduleEvent :: EventLoop c mod mods es => EffT' c (mod ': mods) es IO (STM (ModuleEvent mod))
- Control.System: type family Dependency mod (deps :: [Type]) (mods :: [Type])
+ Control.System: type family Dependency' (c :: Type -> Type -> [Type] -> Type) mod (deps :: [Type]) (mods :: [Type])
- Control.System.EventLoop: eventLoop :: forall (mods :: [Type]). (ConsFDataList (FData :: (Type -> Type) -> [Type] -> Type) mods, System (FData :: (Type -> Type) -> [Type] -> Type) mods) => Eff mods (NoError :: [Type]) ()
+ Control.System.EventLoop: eventLoop :: forall (mods :: [Type]) (es :: [Type]). (ConsFDataList (FData :: (Type -> Type) -> [Type] -> Type) mods, EventLoopSystem (FData :: (Type -> Type) -> [Type] -> Type) mods es) => Eff mods es ()

Files

bench/BenchCatch.hs view
@@ -33,8 +33,8 @@  programMonadEffect :: Int -> ME.EffT mods '[ErrorValue "()" ()] ME.Identity () programMonadEffect = \case-    0 -> ME.effThrow (ErrorValue @"()" ())-    n -> ME.effCatchIn' (programMonadEffect (n - 1)) $ \(ErrorValue @"()" ()) -> ME.effThrow (ErrorValue @"()" ())+    0 -> ME.effThrow (ErrorValue @_ @"()" ())+    n -> ME.effCatchIn' (programMonadEffect (n - 1)) $ \(ErrorValue @_ @"()" ()) -> ME.effThrow (ErrorValue @_ @"()" ()) {-# NOINLINE programMonadEffect #-}  catchMonadEffect :: Int -> Either () ()
monad-effect.cabal view
@@ -7,7 +7,7 @@ -- PVP summary:     +-+------- breaking API changes --                  | | +----- non-breaking API additions --                  | | | +--- code changes with no API change-version:            0.1.0.0+version:            0.2.0.0  -- A short (one-line) description of the package. synopsis:  A fast and lightweight effect system.@@ -73,6 +73,7 @@     -- | This is a small library that gets benefit from inlining and specialisation.     -- therefore we turn on these optimisations     ghc-options: -O2 -fexpose-all-unfoldings -fspecialise-aggressively -flate-dmd-anal+    -- -finfo-table-map -fdistinct-constructor-tables -ddump-to-file -ddump-splices      -- Modules exported by the library.     exposed-modules:  Control.Monad.Effect
src/Control/Monad/Effect.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE DerivingVia, AllowAmbiguousTypes, UndecidableInstances, PatternSynonyms, LinearTypes #-}+{-# LANGUAGE DerivingVia, AllowAmbiguousTypes, UndecidableInstances, LinearTypes, QuantifiedConstraints #-} -- | Module: Control.Monad.Effect -- Description: The module you should import to use for effectful computation --@@ -7,30 +7,62 @@   ( -- * EffTectful computation     EffT', Eff, Pure, EffT, EffL, PureL, EffLT   , ErrorText(..), errorText, ErrorValue(..), errorValue, MonadThrowError(..)+  , MonadFailError(..)++  -- * Natural Transformation+  , baseTransform++  -- * Embedding effects   , embedEffT, embedMods, embedError++  -- * Running EffT   , runEffT, runEffT_, runEffT0, runEffT01, runEffT00   , runEffTNoError   , runEffTOuter, runEffTOuter', runEffTOuter_   , runEffTIn, runEffTIn', runEffTIn_+  , replaceEffTIn++  -- * Catching and throwing algebraic exceptions   , effCatch, effCatchAll, effCatchSystem   , effCatchIn, effCatchIn'-  , effThrow, effThrowIn+  , effThrow, effThrowIn, effThrowEList, effThrowEListIn++  -- * Catching exceptions from base+  , effTry, effTryIn, effTryWith, effTryInWith   , effTryIO, effTryIOIn, effTryIOWith, effTryIOInWith++  -- * Converting values to error   , effEither, effEitherWith   , effEitherIn, effEitherInWith+  , effEitherSystemException   , effMaybeWith, effMaybeInWith   , pureMaybeInWith, pureEitherInWith   , baseEitherIn, baseEitherInWith, baseMaybeInWith-  , errorToEither, errorToEitherAll, eitherAllToEffect++  -- * Converting error to values+  , errorToEither, errorToEitherAll, eitherAllToEffect, errorInToEither+  , errorToMaybe, errorInToMaybe, errorToResult+  +  -- * Transforming error+  , mapError++  -- * Lifting IO   , liftIOException, liftIOAt, liftIOSafeWith, liftIOText, liftIOPrepend-  , effEitherSystemException +  -- * Bracket pattern+  , maskEffT, generalBracketEffT, bracketEffT++  -- * Looping+  , foreverEffT+   -- * Concurrency-  , forkEffT, forkEffTSafe, asyncEffT+  , forkEffT, forkEffTFinally, forkEffTSafe, asyncEffT+  , restoreAsync, restoreAsync_    -- * No Error-  , declareNoError   , checkNoError+  , declareNoError+  , embedNoError   , NoError    -- * Modules@@ -45,24 +77,24 @@   , SystemError(..)    -- * Re-exports-  , MonadIO(..)+  , MonadIO(..), MonadMask   , ConsFDataList, FList, FData   , Identity(..)   , InList, In'   , In, InL   , module Data.TypeList.ConsFData.Pattern   , fNil+   -- * Result types   , Result(..), EList(..)   ) where --- import Control.Parallel.Strategies import Control.Concurrent import Control.Concurrent.Async import Control.Exception as E hiding (TypeError) import Control.Monad import Control.Monad.Base-import Control.Monad.Catch+import Control.Monad.Catch as Catch import Control.Monad.IO.Class import Control.Monad.RS.Class import Control.Monad.Trans@@ -79,6 +111,7 @@ import Data.TypeList.FData import GHC.TypeError import GHC.TypeLits+import GHC.Stack (HasCallStack)  -- | EffTectful computation, using modules as units of effect -- the tick is used to indicate the polymorphic type c which is the data structure used to store the modules.@@ -180,9 +213,11 @@     return (RSuccess a, ss)   {-# INLINE liftIO #-} -instance Monad m => MonadReadable (SystemRead c mods) (EffT' c mods es m) where+instance Monad m => MonadReadOnly (SystemRead c mods) (EffT' c mods es m) where   query = EffT' $ \rs ss -> return (RSuccess rs, ss)   {-# INLINE query #-}++instance Monad m => MonadReadable (SystemRead c mods) (EffT' c mods es m) where   local f (EffT' eff) = EffT' $ \rs ss -> eff (f rs) ss   {-# INLINE local #-} @@ -223,18 +258,83 @@   -- _  -- | The error in throwM is thrown as MonadThrowError, which is a wrapper for SomeException.-instance (Monad m, ConsFDataList c mods, InList MonadThrowError es) => MonadThrow (EffT' c mods es m) where+instance (Monad m, InList MonadThrowError es) => MonadThrow (EffT' c mods es m) where   throwM = effThrowIn . MonadThrowError . toException   {-# INLINE throwM #-}  -- | this can only catch MonadThrowError, other errors are algebraic and should be caught by effCatch, effCatchIn, effCatchAll-instance (Monad m, ConsFDataList c mods, InList MonadThrowError es) => MonadCatch (EffT' c mods es m) where+instance (Monad m, InList MonadThrowError es) => MonadCatch (EffT' c mods es m) where   catch ma handler = effCatchIn' ma $ \(MonadThrowError e) ->     case fromException e of       Just e' -> handler e'       Nothing -> effThrowIn $ MonadThrowError e   {-# INLINE catch #-} +-- | Used for MonadFail instances only+newtype MonadFailError = MonadFailError String+instance Show MonadFailError where+  show (MonadFailError s) = "MonadFailError { " ++ s ++ " }"++-- | When MonadFailError is in the error list, we can use MonadFail instance+instance (Monad m, InList MonadFailError es) => MonadFail (EffT' c mods es m) where+  fail = effThrowIn . MonadFailError+  {-# INLINE fail #-}++baseTransform :: ( forall a. m a -> n a ) -> EffT' c mods es m b -> EffT' c mods es n b+baseTransform f = \(EffT' eff) -> EffT' $ \rs ss -> f (eff rs ss)+{-# INLINE baseTransform #-}++-- | Do not use Control.Applicative.forever, use this instead+foreverEffT :: Monad m => EffT' c mods es m a -> EffT' c mods es m never_returns+foreverEffT eff = do+  _ <- eff+  foreverEffT eff+{-# INLINE foreverEffT #-}+---------------------------------------------------------+-- bracket patterns+--+-- | Mask asynchronous exceptions in the base monad,+-- an `unMask` function is provided to the argument to selectively unmask parts of the computation+maskEffT+  :: forall c mods es m b+  .  MonadMask m+  => HasCallStack+  => ((forall c' mods' es' a. EffT' c' mods' es' m a -> EffT' c' mods' es' m a) -> EffT' c mods es m b)+  -> EffT' c mods es m b+maskEffT actionUsingUnmask = EffT' $ \rs ss -> Catch.mask $ \unmask ->+  unEffT' (actionUsingUnmask $ \(EffT' eff) -> EffT' $ \rs' ss' -> unmask (eff rs' ss')) rs ss+{-# INLINE maskEffT #-}++-- | The generalized bracket pattern for EffT+-- exceptions outside the error list are not caught.+-- To deal with them, make them into the error list first (like using effTryIOWith).+generalBracketEffT+  :: MonadMask m+  => HasCallStack+  => EffT' c mods es m a                        -- ^ acquire resource+  -> (a -> Result es' b -> EffT' c mods es m o) -- ^ release resource, and return the result+  -> (a -> EffT' c mods es' m b)                -- ^ action using the resource+  -> EffT' c mods es m o+generalBracketEffT acquire release action = maskEffT $ \unMaskEffT -> do+  resource <- acquire+  result <- embedNoError $ unMaskEffT (errorToResult $ action resource)+  release resource result+{-# INLINABLE generalBracketEffT #-}++-- | A simpler version of `generalBracketEffT` where the release function does not depend on the result of the action and error types are the same.+bracketEffT :: (MonadMask m, HasCallStack)+  => EffT' c mods es m a         -- ^ acquire resource+  -> (a -> EffT' c mods es m ()) -- ^ release resource only+  -> (a -> EffT' c mods es m b)  -- ^ action using the resource+  -> EffT' c mods es m b+bracketEffT acquire release = generalBracketEffT+  acquire+  (\a result -> case result of+      RSuccess b -> release a >> return b+      RFailure e -> release a >> EffT' (\_ ss -> return (RFailure e, ss))+  )+{-# INLINABLE bracketEffT #-}+ -- | The states on the separate thread will diverge, and will be discarded. -- when exception occurs, the thread quits forkEffT :: forall c mods es m. (MonadIO m, MonadBaseControl IO m) => EffT' c mods es m () -> EffT' c mods NoError m ThreadId@@ -245,6 +345,24 @@   return (RSuccess forkedEff, ss) {-# INLINE forkEffT #-} +-- | Forks and runs the finalizer when the thread ends, either normally or via exception.+forkEffTFinally :: forall c mods es noError m a.+  ( MonadIO m+  , MonadBaseControl IO m+  , MonadMask m+  , SubListEmbed es (AddIfNotElem SomeAsyncException es)+  , InList SomeAsyncException (AddIfNotElem SomeAsyncException es)+  )+  => EffT' c mods es m a+  -> ((Result (AddIfNotElem SomeAsyncException es) a, SystemState c mods) -> EffT' c mods NoError m ())+  -> EffT' c mods noError m ThreadId+forkEffTFinally eff finalizer = embedError $ do+  rs <- query+  ss <- get+  maskEffT $ \unmask -> forkEffT $ do+    eres <- lift $ unEffT' (effTryIn @SomeAsyncException $ embedError $ unmask eff) rs ss+    finalizer eres+ -- | The states on the separate thread will diverge, and will be discarded. -- forces you to deal with all the exceptions inside the thread, so the thread won't die in an unexpected way. forkEffTSafe :: forall c mods m. (MonadIO m, MonadBaseControl IO m) => EffT' c mods NoError m () -> EffT' c mods NoError m ThreadId@@ -253,13 +371,53 @@  -- | The states on the separate thread will diverge, and will be returned as an Async type. asyncEffT-  :: forall c mods es m a. (MonadIO m, MonadBaseControl IO m)+  :: forall c mods es m a. (MonadBaseControl IO m)   => EffT' c mods es m a -> EffT' c mods NoError m (Async (StM m (Result es a, SystemState c mods))) asyncEffT eff = EffT' $ \rs ss -> do   asyncEff <- liftBaseWith $ \runInBase -> async (runInBase $ unEffT' eff rs ss)   return (RSuccess asyncEff, ss) {-# INLINE asyncEffT #-} +-- | Note: this function seems to be a bit problematic,+-- it seems to cause memory leak. Needs investigation.+-- -- | A simpler version of asyncEffT that only returns the Result value, discarding the new state.+-- asyncEffT_ ::+--   ( MonadIO m+--   , MonadBaseControl IO m+--   , StM m (Result es a, SystemState c mods) ~ (Result es a, SystemState c mods)+--   )+--   => EffT' c mods es m a -> EffT' c mods NoError m (Async (Result es a))+-- asyncEffT_ eff = fmap fst <$> asyncEffT eff+-- {-# INLINE asyncEffT_ #-}++-- | Restores the EffT' computation from an Async value created by asyncEffT.+-- State will be replaced by the state inside the Async when it finishes.+restoreAsync ::+  ( MonadIO m, MonadBaseControl IO m )+  => Async (StM m (Result es a, SystemState c mods)) -> EffT' c mods es m a+restoreAsync asyncSt = EffT' $ \_ _ -> do+  res' <- liftIO $ do+    res <- liftIO (wait asyncSt)+    return $ restoreM res+  (ea, ss') <- res'+  return (ea, ss')+{-# INLINE restoreAsync #-}++-- | Restores the EffT' computation from an Async value created by asyncEffT.+-- But the state on the current thread is kept, discarding the state inside the Async when it finishes.+restoreAsync_ :: forall c mods es m a.+  ( MonadIO m+  , MonadBaseControl IO m+  )+  => Async (StM m (Result es a, SystemState c mods)) -> EffT' c mods es m a+restoreAsync_ asyncSt = EffT' $ \_ ss -> do+  res' <- liftIO $ do+    res <- liftIO (wait asyncSt)+    return $ restoreM res+  (ea, _ss' :: SystemState c mods) <- res'+  return (ea, ss)+{-# INLINE restoreAsync_ #-}+ -- | embed smaller effect into larger effect embedEffT :: forall mods mods' m c es es' a. (SubList c mods mods', SubListEmbed es es', Monad m)   => EffT' c mods es m a -> EffT' c mods' es' m a@@ -285,6 +443,10 @@ embedError = embedEffT {-# INLINE embedError #-} +embedNoError :: forall c mods es m a. (Monad m) => EffT' c mods NoError m a -> EffT' c mods es m a+embedNoError = embedEffT+{-# INLINE embedNoError #-}+ -- | Run the EffT' computation with data needed, returns the potential error result and the new state in the base monad. runEffT :: forall mods es m c a. Monad m => SystemRead c mods -> SystemState c mods -> EffT' c mods es m a -> m (Result es a, SystemState c mods) runEffT rs ss = \eff -> unEffT' eff rs ss@@ -376,6 +538,28 @@   -> EffT' c (Remove (FirstIndex mod mods) mods) es m a runEffTIn_ mread mstate eff = fst <$> runEffTIn @mod @mods mread mstate eff {-# INLINE runEffTIn_ #-}++-- | Replace a module inside EffT' with another module.+replaceEffTIn :: forall mod mod' mods mods' es m c a.+  ( ReplaceElem c mods+  , mods' ~ Replace (FirstIndex mod mods) mod' mods+  , Monad m+  , In' c mod mods+  )+  => (ModuleRead mod -> ModuleState mod -> (ModuleRead mod', ModuleState mod'))+  -> (ModuleRead mod -> ModuleState mod -> ModuleState mod' -> ModuleState mod)+  -> EffT' c mods' es m a+  -> EffT' c mods  es m a+replaceEffTIn replaceFunction recoverFunction eff = EffT' $ \modsRead modsState -> do+  let (mod'Read, mod'State) = replaceFunction (getIn @c @mod modsRead) (getIn @c @mod modsState)+      rs = replaceElem (singFirstIndex @mod @mods) mod'Read modsRead+      ss = replaceElem (singFirstIndex @mod @mods) mod'State modsState+  (ea, ss') <- unEffT' eff rs ss+  case ea of+    RSuccess a  -> returnStrict (RSuccess a , unReplaceElem (singFirstIndex @mod @mods) (Proxy @mod') (recoverFunction (getIn @c @mod modsRead) (getIn @c @mod modsState)) ss')+    RFailure es -> returnStrict (RFailure es, unReplaceElem (singFirstIndex @mod @mods) (Proxy @mod') (recoverFunction (getIn @c @mod modsRead) (getIn @c @mod modsState)) ss')+{-# INLINE replaceEffTIn #-}+ -------------------------------------- instances --------------------------------------  -- | The unit of Effect, a module is a type with certain associated data family types@@ -486,6 +670,38 @@     Left e'  -> return (RFailure $ EHead $ f e', s) {-# INLINE liftIOSafeWith #-} +-- | Try in the base monad (with MonadCatch), adding as the first error in the error list.+effTry :: (Exception e, MonadCatch m) => EffT' c mods es m a -> EffT' c mods (e : es) m a+effTry eff = EffT' $ \rs ss -> do+  ePair <- Catch.try (unEffT' eff rs ss)+  case ePair of+    Left e -> return (RFailure $ EHead e, ss)+    Right (eResult, stateMods) -> return (resultMapErrors ETail eResult, stateMods)+{-# INLINE effTry #-}++effTryWith :: forall e e' es c mods m a. (Exception e, MonadCatch m)+  => (e -> e') -> EffT' c mods es m a -> EffT' c mods (e' : es) m a+effTryWith f eff = EffT' $ \rs ss -> do+  ePair <- Catch.try (unEffT' eff rs ss)+  case ePair of+    Left e -> return (RFailure $ EHead $ f e, ss)+    Right (eResult, stateMods) -> return (resultMapErrors ETail eResult, stateMods)+{-# INLINE effTryWith #-}++effTryInWith :: forall e e' es c mods m a. (Exception e, MonadCatch m, InList e' es)+  => (e -> e') -> EffT' c mods es m a -> EffT' c mods es m a+effTryInWith f eff = EffT' $ \rs ss -> do+  ePair <- Catch.try (unEffT' eff rs ss)+  case ePair of+    Left e                     -> return (RFailure $ embedE $ f e, ss)+    Right (eResult, stateMods) -> return (eResult, stateMods)+{-# INLINE effTryInWith #-}++effTryIn :: forall e es c mods m a. (Exception e, MonadCatch m, InList e es)+  => EffT' c mods es m a -> EffT' c mods es m a+effTryIn = effTryInWith @e id+{-# INLINE effTryIn #-}+ -- | @try@ on the Base monad IO, adding as the first error in the error list. -- It is recommended that you wrap low-level routines into algebraic error in the first place instead of using this function. effTryIO :: Exception e => EffT' c mods es IO a -> EffT' c mods (e : es) IO a@@ -518,6 +734,16 @@     Right (eResult, stateMods) -> return (eResult, stateMods) {-# INLINE effTryIOInWith #-} +-- | Transform the first error in the error list+mapError :: Monad m => (e1 -> e2) -> EffT' c mods (e1 : es) m a -> EffT' c mods (e2 : es) m a+mapError f eff = EffT' $ \rs ss -> do+  (eResult, stateMods) <- unEffT' eff rs ss+  return (resultMapErrors (\case+    EHead e -> EHead (f e)+    ETail es -> ETail es)+      eResult, stateMods)+{-# INLINE mapError #-}+ -- | Convert the first error in the effect to Either errorToEither :: Monad m => EffT' c mods (e : es) m a -> EffT' c mods es m (Either e a) errorToEither eff = EffT' $ \rs ss -> do@@ -528,6 +754,26 @@     RFailure (ETail es) -> return (RFailure es, stateMods) {-# INLINE errorToEither #-} +-- | Convert the first error in the effect to Maybe+errorToMaybe :: Monad m => EffT' c mods (e : es) m a -> EffT' c mods es m (Maybe a)+errorToMaybe = fmap (either (const Nothing) Just) . errorToEither+{-# INLINE errorToMaybe #-}++-- | Specify the error type to convert to Either. Use TypeApplications to specify the error type.+errorInToEither :: forall e es mods m c a. (Monad m, InList e es) => EffT' c mods es m a -> EffT' c mods (Remove (FirstIndex e es) es) m (Either e a)+errorInToEither eff = EffT' $ \rs ss -> do+  (eResult, stateMods) <- unEffT' eff rs ss+  case getElemRemoveResult (singIndex @e @es) eResult of+    Left e -> case proofIndex @e @es of+      Refl -> return (RSuccess (Left e), stateMods)+    Right eResult' -> return (fmap Right eResult', stateMods)+{-# INLINE errorInToEither #-}++-- | Specify the error type to convert to Maybe. Use TypeApplications to specify the error type.+errorInToMaybe :: forall e es mods m c a. (Monad m, InList e es) => EffT' c mods es m a -> EffT' c mods (Remove (FirstIndex e es) es) m (Maybe a)+errorInToMaybe = fmap (either (const Nothing) Just) . errorInToEither @e+{-# INLINE errorInToMaybe #-}+ -- | Convert all errors to Either errorToEitherAll :: Monad m => EffT' c mods es m a -> EffT' c mods NoError m (Either (EList es) a) errorToEitherAll eff = EffT' $ \rs ss -> do@@ -613,14 +859,22 @@ {-# INLINE effCatchAll #-}  -- | Throw into the error list-effThrowIn :: (Monad m, InList e es) => e -> EffT' c mods es m a+effThrowIn :: forall e c mods es m a. (Monad m, InList e es) => e -> EffT' c mods es m a effThrowIn e = EffT' $ \_ s -> pure (RFailure $ embedE e, s) {-# INLINE effThrowIn #-}  -- | Throw into the error list-effThrow :: (Monad m, InList e es) => e -> EffT' c mods es m a+effThrow :: forall e c mods es m a. (Monad m, InList e es) => e -> EffT' c mods es m a effThrow = effThrowIn {-# INLINE effThrow #-}++effThrowEList :: forall es c mods m a. (Monad m) => EList es -> EffT' c mods es m a+effThrowEList es = EffT' $ \_ s -> pure (RFailure es, s)+{-# INLINE effThrowEList #-}++effThrowEListIn :: forall es es' c mods m a. (Monad m, NonEmptySubList es es') => EList es -> EffT' c mods es' m a+effThrowEListIn es = EffT' $ \_ s -> pure (RFailure $ subListEListEmbed es, s)+{-# INLINE effThrowEListIn #-}  -- | Turn an Either return type into the error list with a function, adding the error type if it is not already in the error list. -- The inner monad type needs to be precise due to the way type inference works.
src/Control/Monad/RS/Class.hs view
@@ -3,10 +3,12 @@ -- simple and extensible state and read effects. module Control.Monad.RS.Class where +import Control.Monad.Trans+ -- | A class for monads that can read a value of type 'r'. -- without the functional dependencies, so you can read different types of values-class Monad m => MonadReadable r m where-  {-# MINIMAL query, local #-}+-- This ReadOnly has no 'local' method+class Monad m => MonadReadOnly r m where   -- | Query the monad for a value of type 'r'.   query :: m r @@ -15,6 +17,9 @@   queries f = f <$> query   {-# INLINE queries #-} +-- | A class for monads that can read a value of type 'r'.+-- without the functional dependencies, so you can read different types of values+class MonadReadOnly r m => MonadReadable r m where   local :: (r -> r) -> m a -> m a  -- | A class for monads that can maintain a state of type 's'.@@ -36,4 +41,15 @@   modify f = do     s <- get     put (f s)+  {-# INLINE modify #-}++instance {-# OVERLAPPABLE #-} (MonadTrans t, MonadReadOnly r m) => MonadReadOnly r (t m) where+  query = lift query+  {-# INLINE query #-}+instance {-# OVERLAPPABLE #-} (MonadTrans t, MonadStateful s m) => MonadStateful s (t m) where+  get = lift get+  {-# INLINE get #-}+  put = lift . put+  {-# INLINE put #-}+  modify = lift . modify   {-# INLINE modify #-}
src/Control/System.hs view
@@ -1,13 +1,14 @@-{-# LANGUAGE AllowAmbiguousTypes, UndecidableInstances #-}+{-# LANGUAGE AllowAmbiguousTypes, UndecidableInstances, UndecidableSuperClasses #-} module Control.System   (   -- * Module and System     Module(..)--  , System(..), Loadable(..)+  , WithSystem(..) -  , runSystemWithInitData+  , EventLoop(..)+  , EventLoopSystem(..) +  -- * read from module / get state   , askModule, asksModule   , queryModule, queriesModule   , localModule@@ -15,123 +16,85 @@   , putModule, modifyModule    -- * Loadable-  , ModuleInitDataHardCode-  -  , LoadableEnv(..), LoadableArgs(..), SystemEnv(..), SystemArgs(..)-  , SystemInitDataHardCode'-  , SystemInitDataHardCode-  , SystemInitDataHardCodeL-  , Dependency+  , Loadable(..)+  , Dependency, Dependency' +  -- * Small utils+  , detectFlag, detectAllFlags+   ) where  import Control.Applicative import Control.Concurrent.STM import Control.Monad.Effect import Data.Kind+import Data.Maybe+import Data.Text (Text) import Data.TypeList  type family DependencyW (mod :: Type) (deps :: [Type]) (mods :: [Type]) :: Constraint where   DependencyW mod '[] mods = mod `In` (mod : mods)   DependencyW mod (dep ': deps) mods = (dep `In` mods, dep `In` (mod : mods), DependencyW mod deps mods) +type family DependencyW' c (mod :: Type) (deps :: [Type]) (mods :: [Type]) :: Constraint where+  DependencyW' c mod '[] mods = (In' c mod (mod : mods))+  DependencyW' c mod (dep ': deps) mods = (In' c dep mods, In' c dep (mod : mods), DependencyW' c mod deps mods)+ -- | A type family that can be used to generate the constraints -- to make specifying module dependencies easier type family Dependency (mod :: Type) (deps :: [Type]) (mods :: [Type]) :: Constraint where   Dependency mod deps mods = (ConsFDataList FData (mod : mods), DependencyW mod deps mods) -type SystemInitDataHardCode' c mods = c ModuleInitDataHardCode mods-type SystemInitDataHardCode    mods = SystemInitDataHardCode' FData mods-type SystemInitDataHardCodeL   mods = SystemInitDataHardCode' FList mods+type family Dependency' c (mod :: Type) (deps :: [Type]) (mods :: [Type]) :: Constraint where+  Dependency' c mod deps mods = (ConsFDataList c (mod : mods), DependencyW' c mod deps mods)  -- | Run a System of EffT' given initData ----- If error happens at initialization, it will return Left SystemError--- If error happens during normal flow, it will return Right (RFailure SystemError)-runSystemWithInitData :: forall mods es m c a. (ConsFDataList c mods, System c mods, MonadIO m)-  => SystemInitData c mods-  -> EffT' c mods es m a-  -> m-      (Either SystemError -- ^ if error happens at initialization-        ( Result es a     -- ^ if error happens during event loop-        , SystemState c mods)-      )-runSystemWithInitData initData eff = do-  liftIO (runEffT0 (initAllModules @c @mods initData)) >>= \case-    RSuccess (rs, ss)  -> Right <$> runEffT rs ss eff-    RFailure (EHead e) -> return $ Left e---- | Specifies that the module can load after mods are loaded--- in practice we could use--- instance SomeModuleWeNeed `In` mods => Loadable mods SomeModuleToLoad-class Loadable c mod mods where-  {-# MINIMAL initModule #-}-  initModule  :: ModuleInitData mod -> EffT' c mods '[SystemError] IO (ModuleRead mod, ModuleState mod)+class Loadable c mod mods ies where+  {-# MINIMAL withModule #-}+  withModule :: ConsFDataList c (mod : mods) => ModuleInitData mod -> EffT' c (mod : mods) ies IO a -> EffT' c mods ies IO a -  beforeEvent :: EffT' c (mod : mods) NoError IO ()+class EventLoop c mod mods es where+  beforeEvent :: EffT' c (mod : mods) es IO ()   beforeEvent = return ()   {-# INLINE beforeEvent #-} -  afterEvent  :: EffT' c (mod : mods) NoError IO ()+  afterEvent  :: EffT' c (mod : mods) es IO ()   afterEvent = return ()   {-# INLINE afterEvent #-} -  moduleEvent :: EffT' c (mod : mods) NoError IO (STM (ModuleEvent mod))+  moduleEvent :: EffT' c (mod : mods) es IO (STM (ModuleEvent mod))   moduleEvent = return empty   {-# INLINE moduleEvent #-} -  handleEvent :: ModuleEvent mod -> EffT' c (mod : mods) NoError IO ()+  handleEvent :: ModuleEvent mod -> EffT' c (mod : mods) es IO ()   handleEvent _ = return ()   {-# INLINE handleEvent #-} -  releaseModule :: EffT' c (mod : mods) NoError IO () -- ^ release resources, quit module-  releaseModule = return ()-  {-# INLINE releaseModule #-}--data family ModuleInitDataHardCode mod :: Type--class Loadable c mod mods => LoadableEnv c mod mods where-  readInitDataFromEnv :: ModuleInitDataHardCode mod -> EffT' c '[] '[SystemError] IO (ModuleInitData mod)-  -- ^ Read module init data from environment, or other means-  -- one can change this to SystemInitData mods -> IO (ModuleInitData mod)--class Loadable c mod mods => LoadableArgs c mod mods where-  readInitDataFromArgs :: ModuleInitDataHardCode mod -> [String] -> EffT' c '[] '[SystemError] IO (ModuleInitData mod)-  -- ^ Read module init data from command line arguments, or using comand line arguments to read other things-  -- one can change this to SystemInitData mods -> [String] -> IO (ModuleInitData mod)- ------------------------------------------system : a list of modules------------------------------------------ -- | System is a list of modules loaded in sequence with dependency verification -- -- the last module in the list is the first to be loaded -- and also the first to execute beforeEvent and afterEvent-class System c mods where-  initAllModules :: ConsFDataList c mods => SystemInitData c mods -> EffT' c '[] '[SystemError] IO (SystemRead c mods, SystemState c mods)--  listenToEvents :: ConsFDataList c mods => EffT' c mods '[] IO (STM (SystemEvent mods))--  handleEvents :: ConsFDataList c mods => SystemEvent mods -> EffT' c mods '[] IO ()--  beforeSystem :: ConsFDataList c mods => EffT' c mods '[] IO ()+class WithSystem c mods initEs where+  withSystem :: ConsFDataList c mods => SystemInitData c mods -> EffT' c mods initEs IO a -> EffT' c '[] initEs IO a -  afterSystem  :: ConsFDataList c mods => EffT' c mods '[] IO ()+class EventLoopSystem c mods es where+  listenToEvents :: ConsFDataList c mods => EffT' c mods es IO (STM (SystemEvent mods)) -  releaseSystem :: ConsFDataList c mods => EffT' c mods '[] IO ()-  -- ^ safely release all resources system acquired-  -- Warning: releaseSystem is done in reverse order of initAllModules-  -- i.e. the head of the list is the first to be released+  handleEvents :: ConsFDataList c mods => SystemEvent mods -> EffT' c mods es IO () -class System c mods => SystemEnv c mods where-  readSystemInitDataFromEnv :: ConsFDataList c mods => SystemInitDataHardCode' c mods -> EffT' c '[] '[SystemError] IO (SystemInitData c mods)+  beforeSystem :: ConsFDataList c mods => EffT' c mods es IO () -class System c mods => SystemArgs c mods where-  readSystemInitDataFromArgs :: ConsFDataList c mods => SystemInitDataHardCode' c mods -> [String] -> EffT' c '[] '[SystemError] IO (SystemInitData c mods)+  afterSystem  :: ConsFDataList c mods => EffT' c mods es IO ()  -- | base case for system-instance System c '[] where-  initAllModules _ = return (fNil, fNil)-  {-# INLINE initAllModules #-}+instance WithSystem c '[] ies where+  withSystem _ = id+  -- return (fNil, fNil)+  {-# INLINE withSystem #-} +instance EventLoopSystem c '[] es where   listenToEvents = return empty   {-# INLINE listenToEvents #-} @@ -144,63 +107,39 @@   afterSystem = return ()   {-# INLINE afterSystem #-} -  releaseSystem = return ()-  {-# INLINE releaseSystem #-}--instance SystemEnv c '[] where-  readSystemInitDataFromEnv _ = return fNil-  {-# INLINE readSystemInitDataFromEnv #-}--instance SystemArgs c '[] where-  readSystemInitDataFromArgs _ _ = do-    return fNil-  {-# INLINE readSystemInitDataFromArgs #-}- -- | Inductive instance for system-instance (SystemModule mod, System c mods, Loadable c mod mods) => System c (mod ': mods) where-  initAllModules (x :*** xs) = do-    (rs, ss)  <- initAllModules xs-    (er, ss') <- liftIO $ runEffT rs ss $ initModule @c @mod x-    case er of-      RSuccess (r', s') -> return (r' :*** rs, s' :*** ss')-      RFailure (EHead e) -> effThrowIn e-  {-# INLINE initAllModules #-}+instance (SystemModule mod, WithSystem c mods ies, Loadable c mod mods ies) => WithSystem c (mod ': mods) ies where+  withSystem (x :*** xs) = withSystem @c @mods @ies xs . withModule @c @mod @mods @ies x+  {-# INLINE withSystem #-} +instance (SystemModule mod, EventLoop c mod mods es, EventLoopSystem c mods es) => EventLoopSystem c (mod ': mods) es where   beforeSystem = do-    embedEffT $ beforeSystem @c @mods-    beforeEvent @c @mod+    embedMods $ beforeSystem @c @mods @es+    beforeEvent @c @mod @mods @es   {-# INLINE beforeSystem #-}    afterSystem = do-    embedEffT $ afterSystem @c @mods-    afterEvent @c @mod+    embedMods $ afterSystem @c @mods @es+    afterEvent @c @mod @mods @es   {-# INLINE afterSystem #-}    listenToEvents = do-    tailEvents <- embedEffT $ listenToEvents @c @mods-    headEvent  <- moduleEvent @c @mod+    tailEvents <- embedMods $ listenToEvents @c @mods @es+    headEvent  <- moduleEvent @c @mod @mods @es     return $ UHead <$> headEvent <|> UTail <$> tailEvents   {-# INLINE listenToEvents #-} -  handleEvents (UHead x) = handleEvent @c @mod x-  handleEvents (UTail xs) = embedEffT $ handleEvents @_ @mods xs+  handleEvents (UHead x) = handleEvent @c @mod @mods @es x+  handleEvents (UTail xs) = embedMods $ handleEvents @_ @mods @es xs   {-# INLINE handleEvents #-} -  releaseSystem = do-    releaseModule @c @mod-    embedEffT $ releaseSystem @c @mods-  {-# INLINE releaseSystem #-}--instance (SubList c mods (mod:mods), SystemModule mod, SystemEnv c mods, Loadable c mod mods, LoadableEnv c mod mods) => SystemEnv c (mod ': mods) where-  readSystemInitDataFromEnv (im :*** ims) = do-    xs <- readSystemInitDataFromEnv @c @mods ims-    x  <- readInitDataFromEnv @c @mod @mods im-    return $ x :*** xs-  {-# INLINE readSystemInitDataFromEnv #-}+detectFlag :: String -> (String -> Either Text a) -> [String] -> Maybe (Either Text a)+detectFlag flag parser = listToMaybe . detectAllFlags flag parser -instance (SubList c mods (mod:mods), SystemModule mod, SystemArgs c mods, Loadable c mod mods, LoadableArgs c mod mods) => SystemArgs c (mod ': mods) where-  readSystemInitDataFromArgs (im :*** ims) args = do-    xs <- readSystemInitDataFromArgs @c @mods ims args-    x  <- readInitDataFromArgs @c @mod @mods im args-    return $ x :*** xs-  {-# INLINE readSystemInitDataFromArgs #-}+detectAllFlags :: String -> (String -> Either Text a) -> [String] -> [Either Text a]+detectAllFlags _ _ [] = []+detectAllFlags flag parser list = go list+  where+    go (x:y:xs) | x == flag = parser y : go xs+                | otherwise = go (y:xs)+    go _ = []
src/Control/System/EventLoop.hs view
@@ -1,24 +1,13 @@+{-# LANGUAGE AllowAmbiguousTypes #-} module Control.System.EventLoop where  import Control.System import Control.Monad.Effect import Control.Concurrent.STM -eventLoop :: forall mods . (ConsFDataList FData mods, System FData mods) => Eff mods NoError ()+eventLoop :: forall mods es. (ConsFDataList FData mods, EventLoopSystem FData mods es ) => Eff mods es () eventLoop = do-  beforeSystem-  listenToEvents >>= liftIO . atomically >>= handleEvents @_ @mods-  afterSystem-  eventLoop---- | Avoid runtime error (IO) though, make sure every loop breaking error is in SystemError-eventLoopWithRelease :: forall mods. (ConsFDataList FData mods, System FData mods) => Eff mods NoError ()-eventLoopWithRelease = do-  eventLoop-  releaseSystem---- | When restart, the state is reset to the initial state-eventLoopWithReleaseRestartIO :: forall mods. (ConsFDataList FData mods, System FData mods) => SystemInitData FData mods -> IO ()-eventLoopWithReleaseRestartIO initData = do-  _ <- runSystemWithInitData @mods initData eventLoopWithRelease-  eventLoopWithReleaseRestartIO initData+  beforeSystem @_ @_ @_+  listenToEvents @_ @_ @_ >>= liftIO . atomically >>= handleEvents @_ @mods @es+  afterSystem @_ @_ @_+  eventLoop @mods @es
src/Data/TypeList.hs view
@@ -46,9 +46,14 @@    modifyIn :: (f e -> f e) -> flist f es -> flist f es   default modifyIn :: (ConsFData flist) => (f e -> f e) -> flist f es -> flist f es-  modifyIn f = modifyInS (singFirstIndex @e @es) f+  modifyIn = modifyInS (singFirstIndex @e @es)   {-# INLINE modifyIn #-} +  lensIn :: forall f fun. Functor fun => (f e -> fun (f e)) -> flist f es -> fun (flist f es)+  default lensIn :: (ConsFData flist) => forall fun. Functor fun => (f e -> fun (f e)) -> flist f es -> fun (flist f es)+  lensIn = lensInS (singFirstIndex @e @es)+  {-# INLINE lensIn #-}+ -- | Axiom firstIndexTraverseNotEqElem :: forall e t ts. (NotEq e t, InList e ts) => FirstIndex e (t : ts) :~: Succ (FirstIndex e ts) firstIndexTraverseNotEqElem = unsafeCoerce Refl@@ -81,7 +86,7 @@   {-# INLINE getIn #-}   modifyIn f = \(x :** xs) -> f x :** xs   {-# INLINE modifyIn #-}-  + -- | InListductive case for the In class. UniqueIn e (t : ts),  instance {-# OVERLAPPABLE #-} (NotEq e t, InList e ts) => InList e (t : ts) where   singIndex = case firstIndexTraverseNotEqElem @e @t @ts of@@ -118,6 +123,18 @@ class SubListEmbed (ys :: [Type]) (xs :: [Type]) where   subListResultEmbed :: Result ys a -> Result xs a -- ^ Embed the result of a sublist operation. +class NonEmptySubList (ys :: [Type]) (xs :: [Type]) where+  subListEListEmbed :: EList ys -> EList xs++instance NonEmptySubList '[x] (x:xs) where+  subListEListEmbed (EHead x) = EHead x+  {-# INLINE subListEListEmbed #-}++instance (InList y xs, NonEmptySubList ys xs) => NonEmptySubList (y:ys) xs where+  subListEListEmbed (EHead y)  = embedE y+  subListEListEmbed (ETail ys) = subListEListEmbed ys+  {-# INLINE subListEListEmbed #-}+ subListUpdateF :: (SubList flist ys xs) => flist f xs -> flist f ys -> flist f xs subListUpdateF xs ys = subListModifyF (const ys) xs {-# INLINE subListUpdateF #-}@@ -138,6 +155,16 @@   subListResultEmbed (RFailure (ETail ys)) = subListResultEmbed (RFailure ys)   {-# INLINE subListResultEmbed #-} +instance {-# INCOHERENT #-} SubList c xs xs where+  getSubListF = id+  {-# INLINE getSubListF #-}+  subListModifyF = id+  {-# INLINE subListModifyF #-}++instance {-# INCOHERENT #-} SubListEmbed xs xs where+  subListResultEmbed = id+  {-# INLINE subListResultEmbed #-}+ -- | Induction case for the SubList class. instance (In' c y xs, ConsFDataList c (y:ys), SubList c ys xs) => SubList c (y : ys) xs where   getSubListF xs = consF0 (getIn xs) (getSubListF xs)@@ -152,13 +179,3 @@   {-# INLINE getSubListF #-}   subListModifyF f (x :*** xs) = x :*** f xs   {-# INLINE subListModifyF #-}--instance {-# INCOHERENT #-} SubList c xs xs where-  getSubListF = id-  {-# INLINE getSubListF #-}-  subListModifyF = id-  {-# INLINE subListModifyF #-}--instance {-# INCOHERENT #-} SubListEmbed xs xs where-  subListResultEmbed = id-  {-# INLINE subListResultEmbed #-}
src/Data/TypeList/ConsFData.hs view
@@ -5,6 +5,7 @@ import Data.TypeList.Families import Data.Type.Equality import Data.Kind (Type)+import Data.Proxy  class ConsFNil (flist :: (Type -> Type) -> [Type] -> Type) where   fNil  :: flist f '[]@@ -23,6 +24,11 @@    unRemoveElem :: SFirstIndex t ts -> f t -> flist f (Remove (FirstIndex t ts) ts) -> flist f ts +class When (NonEmpty (Tail ts)) (ReplaceElem flist (Tail ts)) => ReplaceElem flist (ts :: [Type]) where+  replaceElem :: SFirstIndex t ts -> f t' -> flist f ts -> flist f (Replace (FirstIndex t ts) t' ts)++  unReplaceElem :: SFirstIndex t ts -> Proxy t' -> (f t' -> f t) -> flist f (Replace (FirstIndex t ts) t' ts) -> flist f ts+ class ConsFNil flist => ConsFData flist where   unConsF :: flist f (t : ts) -> (f t, flist f ts) @@ -32,11 +38,16 @@   getInS SFirstIndexZero          (unConsF -> (x, _)) = x   getInS (SFirstIndexSucc Refl n) (unConsF -> (_, xs)) = getInS n xs   {-# INLINE getInS #-}- +   modifyInS :: SFirstIndex t ts -> (f t -> f t) -> flist f ts -> flist f ts   modifyInS SFirstIndexZero          f (unConsF -> (x, xs)) = f x `consF` xs   modifyInS (SFirstIndexSucc Refl n) f (unConsF -> (x, xs)) = x `consF` modifyInS n f xs   {-# INLINE modifyInS #-}++  lensInS :: forall f fun t ts. Functor fun => SFirstIndex t ts -> (f t -> fun (f t)) -> flist f ts -> fun (flist f ts)+  lensInS SFirstIndexZero          f (unConsF -> (x, xs)) = (`consF` xs) <$> f x+  lensInS (SFirstIndexSucc Refl n) f (unConsF -> (x, xs)) = consF x <$> lensInS n f xs+  {-# INLINE lensInS #-}  class   ( WhenNonEmpty ts (ConsFDataList flist (Tail ts))
src/Data/TypeList/FData.hs view
@@ -10,14 +10,14 @@   , module Data.TypeList   ) where -import GHC.Generics (Generic) import Control.DeepSeq (NFData(..))-import Data.TypeList-import Data.TypeList.FData.TH+import Data.Default import Data.Kind (Type)-import Data.Type.Equality import Data.Proxy-import Data.Default+import Data.Type.Equality+import Data.TypeList+import Data.TypeList.FData.TH+import GHC.Generics (Generic)  data family FData (f :: k -> Type) (ts :: [k]) :: Type data instance FData f '[] = FData0@@ -29,12 +29,18 @@ instance (FDataConstraint FData e es, InList e es) => In' FData e es where   getIn      = case proofIndex @e @es of Refl -> getFDataByIndex    (Proxy @(FirstIndex e es))   modifyIn f = case proofIndex @e @es of Refl -> modifyFDataByIndex (Proxy @(FirstIndex e es)) f+  lensIn   f = case proofIndex @e @es of Refl -> lensFDataByIndex   (Proxy @(FirstIndex e es)) f   {-# INLINE getIn #-}   {-# INLINE modifyIn #-}+  {-# INLINE lensIn #-}  class FDataByIndex (n :: Nat) (ts :: [Type]) where   getFDataByIndex    :: Proxy n -> FData f ts -> f (AtIndex ts n)   modifyFDataByIndex :: Proxy n -> (f (AtIndex ts n) -> f (AtIndex ts n)) -> FData f ts -> FData f ts+  lensFDataByIndex   :: Proxy n+                     -> forall fun. (Functor fun)+                     => ( f (AtIndex ts n) -> fun (f (AtIndex ts n)) )+                     -> FData f ts -> fun (FData f ts)  instance   ( WhenNonEmpty ts (ConsFDataList FData (Tail ts))@@ -100,36 +106,48 @@ --   modifyFDataByIndex _ f (FData1 x) = FData1 (f x) --   {-# INLINE getFDataByIndex #-} --   {-# INLINE modifyFDataByIndex #-}+--   lensFDataByIndex _ g (FData1 x) = fmap FData1 (g x)+--   {-# INLINE lensFDataByIndex #-} -- -- instance FDataByIndex Zero '[x1, x2] where --   getFDataByIndex    _   (FData2 x1 _ ) = x1 --   modifyFDataByIndex _ f (FData2 x1 x2) = FData2 (f x1) x2 --   {-# INLINE getFDataByIndex #-} --   {-# INLINE modifyFDataByIndex #-}+--   lensFDataByIndex _ g (FData2 x1 x2) = fmap (\x1' -> FData2 x1' x2) (g x1)+--   {-# INLINE lensFDataByIndex #-} --  -- instance FDataByIndex (Succ Zero) '[x1, x2] where --   getFDataByIndex    _ (FData2 _ x2) = x2 --   modifyFDataByIndex _ f (FData2 x1 x2) = FData2 x1 (f x2) --   {-# INLINE getFDataByIndex #-} --   {-# INLINE modifyFDataByIndex #-}+--   lensFDataByIndex _ g (FData2 x1 x2) = fmap (\x2' -> FData2 x1 x2') (g x2)+--   {-# INLINE lensFDataByIndex #-} --  -- instance FDataByIndex Zero '[x1, x2, x3] where --   getFDataByIndex    _   (FData3 x1 _ _) = x1 --   modifyFDataByIndex _ f (FData3 x1 x2 x3) = FData3 (f x1) x2 x3 --   {-# INLINE getFDataByIndex #-} --   {-# INLINE modifyFDataByIndex #-}+--   lensFDataByIndex _ g (FData3 x1 x2 x3) = fmap (\x1' -> FData3 x1' x2 x3) (g x1)+--   {-# INLINE lensFDataByIndex #-} --  -- instance FDataByIndex Zero '[x1, x2, x3, x4] where --   getFDataByIndex    _   (FData4 x1 _ _ _) = x1 --   modifyFDataByIndex _ f (FData4 x1 x2 x3 x4) = FData4 (f x1) x2 x3 x4 --   {-# INLINE getFDataByIndex #-} --   {-# INLINE modifyFDataByIndex #-}+--   lensFDataByIndex _ g (FData4 x1 x2 x3 x4) = fmap (\x1' -> FData4 x1' x2 x3 x4) (g x1)+--   {-# INLINE lensFDataByIndex #-} --  -- instance FDataByIndex Zero '[x1, x2, x3, x4, x5] where --   getFDataByIndex    _   (FData5 x1 _ _ _ _) = x1 --   modifyFDataByIndex _ f (FData5 x1 x2 x3 x4 x5) = FData5 (f x1) x2 x3 x4 x5 --   {-# INLINE getFDataByIndex #-} --   {-# INLINE modifyFDataByIndex #-}+--   lensFDataByIndex _ g (FData5 x1 x2 x3 x4 x5) = fmap (\x1' -> FData5 x1' x2 x3 x4 x5) (g x1)+--   {-# INLINE lensFDataByIndex #-} -- -- instance UnConsFData FData '[x1] where --   unConsFData (FData1 x1) = (x1, FData0)
src/Data/TypeList/FData/TH.hs view
@@ -102,15 +102,18 @@   let conName   = mkName ("FData" ++ show len)          -- FData1 .. FData5 …       className = mkName "FDataByIndex"                 --''FDataByIndex       fName     = mkName "f"                            -- the function arg+      gName     = mkName "g"                            -- functorial updater       -- x1 .. xn  (term vars)       xNames    = [ mkName ("x" ++ show i) | i <- [1 .. len] ]       xiName    = xNames !! idx                         -- xi (to be focused)+      xiPrime   = mkName (nameBase xiName ++ "'")       -- updated slot       -- x1 .. xn  (type vars)       tNames    = [ mkName ("x" ++ show i) | i <- [1 .. len] ]       tVars     = map VarT tNames        fGetFDataByIndex = mkName "getFDataByIndex"    -- getFDataByIndex       fModifyFDataByIndex  = mkName "modifyFDataByIndex" -- modifyFDataByIndex+      fLensFDataByIndex    = mkName "lensFDataByIndex"    let instHead = AppT                    (AppT (ConT className) (natTy idx))@@ -121,7 +124,7 @@   ----------------------------------------------------------------------       getClause =         Clause [ WildP-               , ConP conName [] (mkGetPats len idx xiName)+               , BangP $ ConP conName [] (mkGetPats len idx xiName)                ]                (NormalB (VarE xiName))                []@@ -140,20 +143,54 @@       modifyClause =         Clause [ WildP                , VarP fName-               , ConP conName [] patVars+               , BangP $ ConP conName [] patVars                ]                (NormalB modifyBody)                []+  ----------------------------------------------------------------------+  -- lensFDataByIndex+  --   lensFDataByIndex _ g (FDataN x1 .. xi .. xn)+  --     = fmap (\xi' -> FDataN x1 .. xi' .. xn) (g xi)+  ----------------------------------------------------------------------+      gCall      = AppE (VarE gName) (VarE xiName) +      rebuiltFields =+        [ if i == idx then VarE xiPrime else VarE (xNames !! i)+        | i <- [0 .. len-1] ]++      rebuildWithXi' = LamE [VarP xiPrime]+                         (foldl AppE (ConE conName) rebuiltFields)++      lensBody = AppE (AppE (VarE 'fmap) rebuildWithXi') gCall++      lensClause =+        Clause [ WildP+               , VarP gName+               , BangP $ ConP conName [] patVars+               ]+               (NormalB lensBody)+               []+   pure $ InstanceD           Nothing           []           instHead           [ FunD fGetFDataByIndex    [getClause]           , FunD fModifyFDataByIndex [modifyClause]+          , FunD fLensFDataByIndex   [lensClause]           , PragmaD $ inline fGetFDataByIndex           , PragmaD $ inline fModifyFDataByIndex+          , PragmaD $ inline fLensFDataByIndex           ]+  -- pure $ InstanceD+  --         Nothing+  --         []+  --         instHead+  --         [ FunD fGetFDataByIndex    [getClause]+  --         , FunD fModifyFDataByIndex [modifyClause]+  --         , PragmaD $ inline fGetFDataByIndex+  --         , PragmaD $ inline fModifyFDataByIndex+  --         ]  generateFDataByIndexInstances :: [(Int, Int)] -> Q [Dec] generateFDataByIndexInstances = mapM (uncurry generateFDataByIndexInstance)
src/Data/TypeList/Families.hs view
@@ -113,6 +113,11 @@   Remove Zero     (t ': ts) = ts   Remove (Succ n) (t ': ts) = t : Remove n ts +type family Replace (e :: Nat) (t :: Type) (ts :: [Type]) :: [Type] where+  Replace e t '[]              = '[]+  Replace Zero     t (u ': ts) = t ': ts+  Replace (Succ n) t (u ': ts) = u ': Replace n t ts+ type family AtIndex (ts :: [Type]) (n :: Nat) :: Type where   AtIndex (t ': ts) 'Zero = t   AtIndex (t ': ts) ('Succ n) = AtIndex ts n
src/Module/RS.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# OPTIONS_GHC -Wno-orphans #-} -- | This module defines two modules (unit of effect) that provides reader and state functionality. -- -- it can be used in the EffT monad transformer@@ -5,6 +7,7 @@  import GHC.Generics (Generic) import Control.DeepSeq (NFData)+import Control.Monad.RS.Class  import Control.Monad.Effect import Data.Kind@@ -13,6 +16,8 @@ import GHC.TypeLits import qualified Control.Monad.State as S +import Control.System+ -- | A module that provides reader functionality data RModule (r :: Type) @@ -56,6 +61,16 @@   newtype ModuleInitData (SNamed name s) = SNamedInitData { sNamedInitState :: s }   data    ModuleEvent (SNamed name s)    = SNamedEvent +instance Loadable c (RModule r) mods ies where+  withModule (RInitData r) = runEffTOuter_ (RRead r) RState+  {-# INLINE withModule #-}+instance EventLoop c (RModule r) mods es++instance Loadable c (SModule s) mods ies where+  withModule (SInitData s) = runEffTOuter_ SRead (SState s)+  {-# INLINE withModule #-}+instance EventLoop c (SModule s) mods es+ embedStateT :: forall s mods errs m c a. (Monad m, In' c (SModule s) mods) => S.StateT s (EffT' c mods errs m) a -> EffT' c mods errs m a embedStateT action = do   SState s <- getModule @(SModule s)@@ -92,6 +107,26 @@   return a {-# INLINE asStateT #-} +-- | Restrict a state module to be read-only RModule+readOnly :: forall s mods errs m a c. (In' c (SModule s) (SModule s : mods), ConsFDataList c (SModule s : mods), ConsFDataList c (RModule s : mods), Monad m)+  => EffT' c (RModule s : mods) errs m a+  -> EffT' c (SModule s : mods) errs m a+readOnly eff = do+  state <- getS @s+  embedEffT $ runEffTOuter_ (RRead state) RState eff+{-# INLINE readOnly #-}++-- readOnlyIn :: forall s errs m a c mods' mods.+--   ( In' c (SModule s) mods+--   , mods' ~ Replace (FirstIndex (SModule s) mods) (RModule s) mods+--   , ReplaceElem c mods+--   , Monad m+--   )+--   => EffT' c mods' errs m a+--   -> EffT' c mods  errs m a+-- readOnlyIn effRO = EffT' $ \modsRead modsState ->+--   _+ runRModule :: (ConsFDataList c (RModule r : mods), Monad m) => r -> EffT' c (RModule r : mods) errs m a -> EffT' c mods errs m a runRModule r = runEffTOuter_ (RRead r) RState {-# INLINE runRModule #-}@@ -146,8 +181,7 @@ {-# INLINE getsS #-}  putS :: forall s mods errs c m. (Monad m, In' c (SModule s) mods) => s -> EffT' c mods errs m ()-putS s = do-  SState _ <- getModule @(SModule s)+putS !s = do   putModule @(SModule s) (SState s) {-# INLINE putS #-} @@ -156,3 +190,24 @@   s <- getS   putS (f s) {-# INLINE modifyS #-}++-- put here to avoid cyclic dependency+instance {-# OVERLAPPABLE #-} (Monad m, In' c (RModule r) mods) => MonadReadOnly r (EffT' c mods errs m) where+  query = askR+  queries = asksR+  {-# INLINE query #-}+  {-# INLINE queries #-}++instance {-# OVERLAPPABLE #-} (Monad m, In' c (RModule r) mods) => MonadReadable r (EffT' c mods errs m) where+  local = localR+  {-# INLINE local #-}++instance {-# OVERLAPPABLE #-} (Monad m, In' c (SModule s) mods) => MonadStateful s (EffT' c mods errs m) where+  get = getS+  put = putS+  modify = modifyS+  gets = getsS+  {-# INLINE get #-}+  {-# INLINE put #-}+  {-# INLINE modify #-}+  {-# INLINE gets #-}
src/Module/RS/QQ.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE RecordWildCards, OverloadedRecordDot #-}+{-# LANGUAGE RecordWildCards, OverloadedRecordDot, ViewPatterns #-} -- | This module provides Template Haskell utilities for generating RModules and SModules with fixed type -- -- The `makeRModule` function generates a reader module, for example@@ -64,9 +64,17 @@ import Language.Haskell.TH.Quote import Text.Parsec +data DataFieldSpec = DataFieldSpec+  { fieldName   :: Name+  , fieldLens   :: Bool -- ^ Whether to generate a lens for this field+  , fieldStrict :: Bool+  , fieldType   :: Type+  }+  deriving Show+ data DataConsSpec = DataConsSpec   { dataConsName :: Name-  , dataFields   :: [(Name, Bool, Type)] -- ^ (fieldName, strictness, fieldType)+  , dataFields   :: [DataFieldSpec]   }   deriving Show @@ -187,15 +195,22 @@   let moduleName = upperHead : rest   pure $ mkName moduleName -parseField :: ParsecT String () Identity (Name, Bool, Type)+parseField :: ParsecT String () Identity DataFieldSpec parseField = do+  lens <- option False (True <$ try (string "Lens" >> many1 space))   fieldName <- parseFieldName   spaces >> char ':' >> char ':' >> spaces   strictness <- option False (True <$ char '!')   typeString <- manyTill anyChar (try (eof <|> void endOfLine))   case parseType typeString of     Left err -> fail $ "Failed to parse type: " ++ show err-    Right type' -> return (fieldName, strictness, type')+    Right type' -> return $ DataFieldSpec+      { fieldName   = fieldName+      , fieldLens   = lens+      , fieldStrict = strictness+      , fieldType   = type'+      }+    -- (fieldName, strictness, type')   where     parseFieldName = mkName <$> do       lowerHead <- lower@@ -215,12 +230,17 @@ mkBang True  = Bang NoSourceUnpackedness SourceStrict mkBang False = Bang NoSourceUnpackedness NoSourceStrictness -updateBang :: (a, Bool, b) -> (a, Bang, b)-updateBang (a, b, c) = (a, mkBang b, c)+updateBang :: DataFieldSpec -> (Name, Bang, Type)+updateBang DataFieldSpec{..} = (fieldName, mkBang fieldStrict, fieldType) -appendName :: String -> (Name, a, b) -> (Name, a, b)-appendName suffix (name, a, b) =-  (mkName $ nameBase name ++ suffix, a, b)+appendName :: String -> DataFieldSpec -> DataFieldSpec+appendName suffix DataFieldSpec{..} =+  DataFieldSpec+    { fieldName   = mkName $ nameBase fieldName ++ suffix+    , fieldLens   = fieldLens+    , fieldStrict = fieldStrict+    , fieldType   = fieldType+    }  inlinePragma :: Name -> Dec inlinePragma name = PragmaD $ InlineP name Inline FunLike AllPhases@@ -237,7 +257,7 @@ dataInstance :: DataInstanceSpec -> Dec dataInstance DataInstanceSpec{..} =   case dataFields dataFamilyConstructor of-    [(_, True, _)] ->+    [fieldStrict -> True] ->       NewtypeInstD [] Nothing         (AppT dataFamilyType dataFamilyInputType)         Nothing@@ -249,8 +269,39 @@         Nothing         [RecC (dataConsName dataFamilyConstructor) $ updateBang <$> dataFields dataFamilyConstructor]         dataFamilyDerivations-  where cancelBang (a, _, c) = (a, mkBang False, c)+  where cancelBang fspec = (fieldName fspec, mkBang False, fieldType fspec) +-- | If fieldName starts with '_', remove the leading underscore for the lens name.+-- Otherwise, prepend an underscore.+lensName :: Name -> Name+lensName (nameBase -> ('_':rest)) = mkName rest+lensName name                     = mkName $ '_' : nameBase name++generateLens :: Type -> DataFieldSpec -> Q [Dec]+generateLens recType DataFieldSpec{..} | fieldLens = do+  let lensFunName = lensName fieldName+      -- | The body of the lens function+      -- _lensName :: Functor f => (fieldType -> f fieldType) -> (DataConsType -> f DataConsType)+      -- _lensName f s = fmap (\x -> s { fieldName = x }) (f (fieldName s))+      lensTypeSig = ForallT [PlainTV funName SpecifiedSpec]+                            [ConT ''Functor `AppT` VarT funName]+                            (ArrowT `AppT` (ArrowT `AppT` fieldType `AppT` (VarT funName `AppT` fieldType))+                                    `AppT` (ArrowT `AppT` recType   `AppT` (VarT funName `AppT` recType))+                            )+      lensFunBody = LamE [VarP fName, VarP sName]+                    $ VarE 'fmap+                      `AppE` LamE [VarP xName] (RecUpdE (VarE sName) [(fieldName, VarE xName)])+                      `AppE` AppE (VarE fName) (AppE (VarE fieldName) (VarE sName))+      funName = mkName "fun"+      fName   = mkName "f"+      sName   = mkName "s"+      xName   = mkName "x"+  sig <- sigD lensFunName (pure lensTypeSig)+  fun <- funD lensFunName [clause [] (normalB (pure lensFunBody)) []]+  prag <- pragInlD lensFunName Inline FunLike AllPhases+  return [sig, fun, prag]+generateLens _ DataFieldSpec{} = return []+ -- * generate data instances for Module <MyModule> -- * generate run<MyModule>, run<MyModule>', run<MyModule>_ and run<MyModule>In, run<MyModule>In', run<MyModule>In_ functions -- * generate type synonym for ModuleRead <MyModule> and ModuleState <MyModule>@@ -259,7 +310,7 @@   let deriveGeneric = [deriveG  | ConfigDeriveGeneric `elem` dconf]       -- deriveNFData  = [deriveNF | ConfigDeriveNFData  `elem` dconf] -  let warnStateNonStrict = any (\(_, strictness, _) -> not strictness) (dataFields stateSpec)+  let warnStateNonStrict = any (\fspec -> not fspec.fieldStrict) (dataFields stateSpec)    when warnStateNonStrict $ reportWarning     $  "The state record for the module " <> nameBase typeName@@ -281,8 +332,10 @@             , dataFamilyDerivations = deriveGeneric             }         ]-      typeSynRead  = TySynD (dataConsName readSpec) [] (ConT ''ModuleRead `AppT` ConT typeName)-      typeSynState = TySynD (dataConsName stateSpec) [] (ConT ''ModuleState `AppT` ConT typeName)+      readType     = ConT ''ModuleRead  `AppT` ConT typeName+      stateType    = ConT ''ModuleState `AppT` ConT typeName+      typeSynRead  = TySynD (dataConsName readSpec)  [] readType+      typeSynState = TySynD (dataConsName stateSpec) [] stateType        runMyModuleName    = mkName $ "run" ++ nameBase typeName       runMyModule'Name   = mkName $ "run" ++ nameBase typeName ++ "'"@@ -453,7 +506,10 @@                  []         ] -  return [ dataTag+  lensDecsR <- concat <$> mapM (generateLens readType)  (dataFields readSpec)+  lensDecsS <- concat <$> mapM (generateLens stateType) (dataFields stateSpec)++  pure $ [ dataTag          , instanceModule          , typeSynRead          , typeSynState@@ -463,7 +519,7 @@          , runMyModuleInSig  , runMyModuleInFun  , inlinePragma runMyModuleInName          , runMyModuleIn'Sig , runMyModuleIn'Fun , inlinePragma runMyModuleIn'Name          , runMyModuleIn_Sig , runMyModuleIn_Fun , inlinePragma runMyModuleIn_Name-         ]+         ] <> lensDecsR <> lensDecsS  generateRModule :: GenerationConfig -> DataConsSpec -> Q [Dec] generateRModule GenerationConfig{ deriveConfigs = dconf, generateSystemInstance } DataConsSpec{dataConsName = modName, dataFields} = do
src/Module/Resource.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE RecordWildCards, UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -- | Provides ResourceT functionality for managing resources module Module.Resource where@@ -26,8 +26,10 @@   liftResourceT = \ResourceT{unResourceT} -> do     rMap <- asksModule resourceRead     liftIO $ unResourceT rMap+  {-# INLINE liftResourceT #-} -instance Loadable c Resource mods where-  initModule _ = do-    istate <- createInternalState-    return (ResourceRead istate, ResourceState)+instance ConsFDataList c (Resource : mods) => Loadable c Resource mods es where+  withModule _ act = bracketEffT createInternalState closeInternalState+    (\istate -> runEffTOuter_ (ResourceRead istate) ResourceState act+    )+  {-# INLINE withModule #-}
test/TH.hs view
@@ -6,11 +6,11 @@ [makeRModule| MyModule   field1 :: !Int-  field2 :: Bool+  Lens field2 :: Bool |]  [makeRSModule| MyRSModule-  readField :: !Int+  Lens readField :: !Int   State stateField :: !Int |]