Abstract RIO to an arbitrary MonadReader instance, which can handle IO.
Modulerio-0.1.25.0Haskell2010
RIO
- 48 types
- 11 classes
- 373 values
- Packagerio-0.1.25.0
- Exports434
- LanguageHaskell2010
- LicenceMIT
- SourceRIO.hs
Custom Prelude
0 declarationsOne of the core features of rio is that it can be used as a Prelude
replacement. Therefore it is best to disable the default Prelude with:
NoImplicitPrelude
pragma:
{-# LANGUAGE NoImplicitPrelude #-}
import RIOSome functions not exported here can be found in RIO.Partial:
fromJust, read, toEnum, pred, succ.
module RIO.Prelude
module RIO.Prelude.Types
The RIO Monad
3 declarationsUsing the environment run in IO the action that requires that environment.
The Reader+IO monad. This is different from a ReaderT because:
It's not a transformer, it hardcodes IO for simpler usage and error messages.
Instances of typeclasses like
MonadLoggerare implemented using classes defined on the environment, instead of using an underlying monad.
Instances13MonadReader, MonadState, MonadWriter, Monad, Functor, Applicative, …
MonadReader env (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOHasStateRef s env => MonadState s (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIO(Monoid w, HasWriteRef w env) => MonadWriter w (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOMonad (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOFunctor (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOApplicative (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOMonadIO (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOMonadThrow (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOPrimMonad (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOMonadUnliftIO (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOSemigroup a => Semigroup (RIO env a)Defined in rio-0.1.25.0 · RIO.Prelude.RIOMonoid a => Monoid (RIO env a)Defined in rio-0.1.25.0 · RIO.Prelude.RIOtype PrimState (RIO env) = PrimState IODefined in rio-0.1.25.0 · RIO.Prelude.RIO
SimpleApp
If all you need is just some default environment that does basic logging and allows spawning processes, then you can use SimpleApp:
{-# LANGUAGE OverloadedStrings #-}
module Main where
main :: IO ()
main =
runSimpleApp $ do
logInfo "Hello World!"Note the OverloadedStrings extension, which is enabled to simplify logging.
module RIO.Prelude.Simple
MonadIO and MonadUnliftIO
9 declarationsSame as askUnliftIO, but returns a monomorphic function instead of a polymorphic newtype wrapper. If you only need to apply the transformation on one concrete type, this function can be more convenient.
Capture the current monadic context, providing the ability to run monadic actions in IO.
See UnliftIO for an explanation of why we need a helper datatype here.
Prior to version 0.2.0.0 of this library, this was a method in the MonadUnliftIO type class. It was moved out due to https://github.com/fpco/unliftio/issues/55.
A helper function for lifting IO a -> IO b functions into any MonadUnliftIO.
Example
liftedTry :: (Exception e, MonadUnliftIO m) => m a -> m (Either e a)
liftedTry m = liftIOOp Control.Exception.try mConvert an action in m to an action in IO.
Convenience function for capturing the monadic context and running an IO action. The UnliftIO newtype wrapper is rarely needed, so prefer withRunInIO to this function.
wrappedWithRunInIO :: MonadUnliftIO n=> (n b -> m b)The wrapper, for instance
IdentityT.-> (forall a. m a -> n a)The inverse, for instance
runIdentityT.-> ((forall a. m a -> IO a) -> IO b)The actual function to invoke withRunInIO with.
-> m b
A helper function for implementing MonadUnliftIO instances.
Useful for the common case where you want to simply delegate to the
underlying transformer.
Note: You can derive MonadUnliftIO for newtypes without this helper function
in unliftio-core 0.2.0.0 and later.
Example
newtype AppT m a = AppT { unAppT :: ReaderT Int (ResourceT m) a }
deriving (Functor, Applicative, Monad, MonadIO)
-- Same as `deriving newtype (MonadUnliftIO)`
instance MonadUnliftIO m => MonadUnliftIO (AppT m) where
withRunInIO = wrappedWithRunInIO AppT unAppTMonads in which IO computations may be embedded. Any monad built by applying a sequence of monad transformers to the IO monad will be an instance of this class.
Instances should satisfy the following laws, which state that liftIO is a transformer of monads:
Methods
liftIO :: IO a -> m aLift a computation from the IO monad. This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations (i.e. IO is the base monad for the stack).
Example
import Control.Monad.Trans.State -- from the "transformers" library printState :: Show s => StateT s IO () printState = do state <- get liftIO $ print stateHad we omitted
liftIO, we would have ended up with this error:• Couldn't match type ‘IO’ with ‘StateT s IO’ Expected type: StateT s IO () Actual type: IO ()The important part here is the mismatch between
StateT s IO ()andIO ().Luckily, we know of a function that takes an
IO aand returns an(m a):liftIO, enabling us to run the program and see the expected results:> evalStateT printState "hello" "hello" > evalStateT printState 3 3
Instances19MonadIO, …
MonadIO QDefined in ghc-internal-9.1401.0 · GHC.Internal.TH.SyntaxMonadIO IODefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Monad.IO.ClassMonadIO (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOMonadIO m => MonadIO (CatchT m)Defined in exceptions-0.10.11 · Control.Monad.Catch.PureMonadIO m => MonadIO (MaybeT m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.MaybeMonadIO m => MonadIO (ExceptT e m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.ExceptMonadIO m => MonadIO (IdentityT m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.IdentityMonadIO m => MonadIO (ReaderT r m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.ReaderMonadIO m => MonadIO (SelectT r m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.SelectMonadIO m => MonadIO (StateT s m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.State.LazyMonadIO m => MonadIO (StateT s m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.State.StrictMonadIO m => MonadIO (WriterT w m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.Writer.CPS(Monoid w, Functor m, MonadIO m) => MonadIO (AccumT w m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.Accum(Monoid w, MonadIO m) => MonadIO (WriterT w m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.Writer.Lazy(Monoid w, MonadIO m) => MonadIO (WriterT w m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.Writer.StrictMonadIO m => MonadIO (ContT r m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.ContMonadIO m => MonadIO (RWST r w s m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.RWS.CPS(Monoid w, MonadIO m) => MonadIO (RWST r w s m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.RWS.Lazy(Monoid w, MonadIO m) => MonadIO (RWST r w s m)Defined in transformers-0.6.1.2 · Control.Monad.Trans.RWS.Strict
Monads which allow their actions to be run in IO.
While MonadIO allows an IO action to be lifted into another monad, this class captures the opposite concept: allowing you to capture the monadic context. Note that, in order to meet the laws given below, the intuition is that a monad must have no monadic state, but may have monadic context. This essentially limits MonadUnliftIO to ReaderT and IdentityT transformers on top of IO.
Laws. For any function run provided by withRunInIO, it must meet the
monad transformer laws as reformulated for MonadUnliftIO:
run . return = returnrun (m >>= f) = run m >>= run . f
Instances of MonadUnliftIO must also satisfy the following laws:
- Identity law
withRunInIO (\run -> run m) = m- Inverse law
withRunInIO (\_ -> m) = liftIO m
As an example of an invalid instance, a naive implementation of
MonadUnliftIO (StateT s m) might be
withRunInIO inner =
StateT $ \s ->
withRunInIO $ \run ->
inner (run . flip evalStateT s)
This breaks the identity law because the inner run m would throw away
any state changes in m.
Methods
withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m bConvenience function for capturing the monadic context and running an IO action with a runner function. The runner function is used to run a monadic action
minIO.
Instances4MonadUnliftIO
MonadUnliftIO IODefined in unliftio-core-0.2.1.0 · Control.Monad.IO.UnliftMonadUnliftIO (RIO env)Defined in rio-0.1.25.0 · RIO.Prelude.RIOMonadUnliftIO m => MonadUnliftIO (IdentityT m)Defined in unliftio-core-0.2.1.0 · Control.Monad.IO.UnliftMonadUnliftIO m => MonadUnliftIO (ReaderT r m)Defined in unliftio-core-0.2.1.0 · Control.Monad.IO.Unlift
Logger
52 declarationsThe logging system in RIO is built upon "log functions", which are accessed in RIO's environment via a class like "has log function". There are two provided:
In the common case: for logging plain text (via Utf8Builder) efficiently, there is LogFunc, which can be created via withLogFunc, and is accessed via HasLogFunc. This provides all the classical logging facilities: timestamped text output with log levels and colors (if terminal-supported) to the terminal. We log output via logInfo, logDebug, etc.
In the advanced case: where logging takes on a more semantic meaning and the logs need to be digested, acted upon, translated or serialized upstream (to e.g. a JSON logging server), we have GLogFunc (as in "generic log function"), and is accessed via HasGLogFunc. In this case, we log output via glog. See the Type-generic logger section for more information.
A vesion of contramapMaybeGLogFunc which supports filering.
Convert a CallStack value into a Utf8Builder indicating the first source location.
TODO Consider showing the entire call stack instead.
Log a value generically.
Log a debug level message with no source.
Log a debug level message with the given source.
Log an error level message with no source.
Log an error level message with the given source.
What accent colors, indexed by Int, is the log func configured to use?
Intended for use by code which wants to optionally add additional color to its log messages.
What color is the log func configured to use for each LogLevel?
Intended for use by code which wants to optionally add additional color to its log messages.
What color is the log func configured to use for secondary content?
Intended for use by code which wants to optionally add additional color to its log messages.
Is the log func configured to use color output?
Intended for use by code which wants to optionally add additional color to its log messages.
Generic, basic function for creating other logging functions.
Log an info level message with no source.
Log an info level message with the given source.
Create a LogOptions value from the given Handle and whether
to perform verbose logging or not. Individiual settings can be
overridden using appropriate set functions.
Logging output is guaranteed to be non-interleaved only for a
UTF-8 Handle in a multi-thread environment.
If the handle is not writable, an exception is thrown immediately.
When Verbose Flag is True, the following happens:
setLogVerboseFormatis called withTruesetLogUseColoris called withTrue(except on Windows)setLogUseLocis called withTruesetLogUseTimeis called withTruesetLogMinLevelis called withDebuglog level
Create a LogOptions value which will store its data in memory. This is primarily intended for testing purposes. This will return both a LogOptions value and an IORef containing the resulting Builder value.
This will default to non-verbose settings and assume there is a
terminal attached. These assumptions can be overridden using the
appropriate set functions.
logOther :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)=> Textlevel
-> Utf8Builder-> m ()
Log a message with the specified textual level and no source.
logOtherS :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)=> Textlevel
-> LogSource-> Utf8Builder-> m ()
Log a message with the specified textual level and the given source.
Write a "sticky" line to the terminal. Any subsequent lines will overwrite this one, and that same line will be repeated below again. In other words, the line sticks at the bottom of the output forever. Running this function again will replace the sticky line with a new sticky line. When you want to get rid of the sticky line, run logStickyDone.
Note that not all LogFunc implementations will support sticky messages as described. However, the withLogFunc implementation provided by this module does.
This will print out the given message with a newline and disable any further stickiness of the line until a new call to logSticky happens.
Log a warn level message with no source.
Log a warn level message with the given source.
Make a custom generic logger. With this you could, for example, write to a database or a log digestion service. For example:
mkGLogFunc (\stack msg -> send (Data.Aeson.encode (JsonLog stack msg)))Create a LogFunc from the given function.
Given a LogOptions value, returns both a new LogFunc and a sub-routine that disposes it.
Intended for use if you want to deal with the teardown of LogFunc yourself, otherwise prefer the withLogFunc function instead.
Disable logging capabilities in a given sub-routine
Intended to skip logging in general purpose implementations, where secrets might be logged accidently.
setLogAccentColors :: (Int -> Utf8Builder)This should be a total function.
-> LogOptions-> LogOptions
Set format method for messages
Default: id
ANSI color codes for LogLevel in the log output.
Default: LevelDebug = "\ESC[32m" -- Green LevelInfo = "\ESC[34m" -- Blue LevelWarn = "\ESC[33m" -- Yellow LevelError = "\ESC[31m" -- Red LevelOther _ = "\ESC[35m" -- Magenta
Set the minimum log level. Messages below this level will not be printed.
Default: in verbose mode, LevelDebug. Otherwise, LevelInfo.
Refer to setLogMinLevel. This modifier allows to alter the verbose format value dynamically at runtime.
Default: in verbose mode, LevelDebug. Otherwise, LevelInfo.
ANSI color codes for secondary content in the log output.
Default: "\ESC[90m" -- Bright black (gray)
Do we treat output as a terminal. If True, we will enable
sticky logging functionality.
Default: checks if the Handle provided to logOptionsHandle is a
terminal with hIsTerminalDevice.
Use the verbose format for printing log messages.
Default: follows the value of the verbose flag.
Refer to setLogVerboseFormat. This modifier allows to alter the verbose format value dynamically at runtime.
Default: follows the value of the verbose flag.
Given a LogOptions value, run the given function with the specified LogFunc. A common way to use this function is:
let isVerbose = False -- get from the command line instead
logOptions' <- logOptionsHandle stderr isVerbose
let logOptions = setLogUseTime True logOptions'
withLogFunc logOptions $ \lf -> do
let app = App -- application specific environment
{ appLogFunc = lf
, appOtherStuff = ...
}
runRIO app $ do
logInfo "Starting app"
myApp
CallStacks are a lightweight method of obtaining a partial call-stack at any point in the program.
A function can request its call-site with the HasCallStack constraint. For example, we can define
putStrLnWithCallStack :: HasCallStack => String -> IO ()
as a variant of putStrLn that will get its call-site and print it,
along with the string given as argument. We can access the
call-stack inside putStrLnWithCallStack with callStack.
:{putStrLnWithCallStack :: HasCallStack => String -> IO ()putStrLnWithCallStack msg = do putStrLn msg putStrLn (prettyCallStack callStack):}
Thus, if we call putStrLnWithCallStack we will get a formatted call-stack
alongside our string.
putStrLnWithCallStack "hello"helloCallStack (from HasCallStack): putStrLnWithCallStack, called at <interactive>:... in interactive:Ghci...
GHC solves HasCallStack constraints in three steps:
If there is a CallStack in scope -- i.e. the enclosing function has a HasCallStack constraint -- GHC will append the new call-site to the existing CallStack.
If there is no CallStack in scope -- e.g. in the GHCi session above -- and the enclosing definition does not have an explicit type signature, GHC will infer a HasCallStack constraint for the enclosing definition (subject to the monomorphism restriction).
If there is no CallStack in scope and the enclosing definition has an explicit type signature, GHC will solve the HasCallStack constraint for the singleton CallStack containing just the current call-site.
CallStacks do not interact with the RTS and do not require compilation
with -prof. On the other hand, as they are built up explicitly via the
HasCallStack constraints, they will generally not contain as much
information as the simulated call-stacks maintained by the RTS.
A CallStack is a [(String, SrcLoc)]. The String is the name of
function that was called, the SrcLoc is the call-site. The list is
ordered with the most recently called function at the head.
NOTE: The intrepid user may notice that HasCallStack is just an
alias for an implicit parameter ?callStack :: CallStack. This is an
implementation detail and should not be considered part of the
CallStack API, we may decide to change the implementation in the
future.
Instances4IsList, Show, NFData, Item
A generic logger of some type msg.
Your GLocFunc can re-use the existing classical logging framework
of RIO, and/or implement additional transforms,
filters. Alternatively, you may log to a JSON source in a database,
or anywhere else as needed. You can decide how to log levels or
severities based on the constructors in your type. You will
normally determine this in your main app entry point.
Instances5Contravariant, Semigroup, Monoid, HasGLogFunc, GMsg
Contravariant GLogFuncDefined in rio-0.1.25.0 · RIO.Prelude.LoggerUse this instance to wrap sub-loggers via mapRIO.
The Contravariant class is available in base 4.12.0.
Semigroup (GLogFunc msg)Defined in rio-0.1.25.0 · RIO.Prelude.LoggerPerform both sets of actions per log entry.
Monoid (GLogFunc msg)Defined in rio-0.1.25.0 · RIO.Prelude.Loggermempty peforms no logging.
HasGLogFunc (GLogFunc msg)Defined in rio-0.1.25.0 · RIO.Prelude.LoggerQuick way to run a RIO that only has a logger in its environment.
type GMsg (GLogFunc msg) = msgDefined in rio-0.1.25.0 · RIO.Prelude.Logger
An app is capable of generic logging if it implements this.
Associated types
type family GMsg env
Instances1HasGLogFunc
HasGLogFunc (GLogFunc msg)Defined in rio-0.1.25.0 · RIO.Prelude.LoggerQuick way to run a RIO that only has a logger in its environment.
Instances3HasLogFunc
HasLogFunc LogFuncDefined in rio-0.1.25.0 · RIO.Prelude.LoggerHasLogFunc SimpleAppDefined in rio-0.1.25.0 · RIO.Prelude.SimpleHasLogFunc LoggedProcessContextDefined in rio-0.1.25.0 · RIO.Process
Level, if any, of your logs. If unknown, use LogOther. Use for
your generic log data types that want to sit inside the classic log
framework.
Methods
getLogLevel :: msg -> LogLevel
Source of a log. This can be whatever you want. Use for your generic log data types that want to sit inside the classic log framework.
Methods
getLogSource :: msg -> LogSource
A logging function, wrapped in a newtype for better error messages.
An implementation may choose any behavior of this value it wishes, including printing to standard output or no action at all.
The log level of a message.
Constructors
Configuration for how to create a LogFunc. Intended to be used with the withLogFunc function.
Where in the application a log message came from. Used for display purposes only.
Display
7 declarationsConvert a ByteString into a Utf8Builder.
NOTE This function performs no checks to ensure that the data is, in fact, UTF8 encoded. If you provide non-UTF8 data, later functions may fail.
Use the Show instance for a value to convert it to a Utf8Builder.
Convert a Utf8Builder value into a lazy Text.
Convert a Utf8Builder value into a strict Text.
Write the given Utf8Builder value to a file.
A typeclass for values which can be converted to a Utf8Builder. The intention of this typeclass is to provide a human-friendly display of the data.
Methods
display :: a -> Utf8BuildertextDisplay :: a -> Text
Instances20Display, …
Display IntegerDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay SomeExceptionDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay IOExceptionDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Int16Defined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Int32Defined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Int64Defined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Int8Defined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay CharDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay DoubleDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay FloatDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay IntDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay WordDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Word16Defined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Word32Defined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Word64Defined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Word8Defined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Utf8BuilderDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay TextDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay TextDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay (ProcessConfig a b c)Defined in rio-0.1.25.0 · RIO.Prelude.Display
A builder of binary data, with the invariant that the underlying data is supposed to be UTF-8 encoded.
Constructors
Instances4IsString, Semigroup, Monoid, Display
IsString Utf8BuilderDefined in rio-0.1.25.0 · RIO.Prelude.DisplaySemigroup Utf8BuilderDefined in rio-0.1.25.0 · RIO.Prelude.DisplayMonoid Utf8BuilderDefined in rio-0.1.25.0 · RIO.Prelude.DisplayDisplay Utf8BuilderDefined in rio-0.1.25.0 · RIO.Prelude.Display
Optics
18 declarationsmicrolens-based Lenses, Traversals, etc.
(%~) applies a function to the target; an alternative explanation is that it is an inverse of sets, which turns a setter into an ordinary function. mapped %~ reverse is the same thing as fmap reverse.
See over if you want a non-operator synonym.
Negating the 1st element of a pair:
(1,2) & _1 %~ negate(-1,2)
Turning all Lefts in a list to upper case:
(mapped._Left.mapped %~ toUpper) [Left "foo", Right "bar"][Left "FOO",Right "bar"]
(^.) applies a getter to a value; in other words, it gets a value out of a structure using a getter (which can be a lens, traversal, fold, etc.).
Getting 1st field of a tuple:
(^. _1) :: (a, b) -> a
(^. _1) = fst
When (^.) is used with a traversal, it combines all results using the Monoid instance for the resulting type. For instance, for lists it would be simple concatenation:
("str","ing") ^. each"string"
The reason for this is that traversals use Applicative, and the Applicative instance for Const uses monoid concatenation to combine “effects” of Const.
A non-operator version of (^.) is called view, and it's a bit more general than (^.) (it works in MonadReader). If you need the general version, you can get it from microlens-mtl; otherwise there's view available in Lens.Micro.Extras.
s ^.. t returns the list of all values that t gets from s.
A Maybe contains either 0 or 1 values:
Just 3 ^.. _Just[3]
Gathering all values in a list of tuples:
[(1,2),(3,4)] ^.. each.each[1,2,3,4]
s ^? t returns the 1st element t returns, or Nothing if t doesn't return anything. It's trivially implemented by passing the First monoid to the getter.
Safe head:
[] ^? eachNothing
[1..3] ^? eachJust 1
Left 1 ^? _RightNothing
Right 1 ^? _RightJust 1
A non-operator version of (^?) is called preview, and – like view – it's a bit more general than (^?) (it works in MonadReader). If you need the general version, you can get it from microlens-mtl; otherwise there's preview available in Lens.Micro.Extras.
lens creates a Lens from a getter and a setter. The resulting lens isn't the most effective one (because of having to traverse the structure twice when modifying), but it shouldn't matter much.
A (partial) lens for list indexing:
ix :: Int -> Lens' [a] a
ix i = lens (!! i) -- getter
(\s b -> take i s ++ b : drop (i+1) s) -- setter
Usage:
>>> [1..9] ^. ix 3
4
>>> [1..9] & ix 3 %~ negate
[1,2,3,-4,5,6,7,8,9]
When getting, the setter is completely unused; when setting, the getter is unused. Both are used only when the value is being modified. For instance, here we define a lens for the 1st element of a list, but instead of a legitimate getter we use undefined. Then we use the resulting lens for setting and it works, which proves that the getter wasn't used:
[1,2,3] & lens undefined (\s b -> b : tail s) .~ 10[10,2,3]
Getting fmap in a roundabout way:
over mapped :: Functor f => (a -> b) -> f a -> f b
over mapped = fmap
Applying a function to both components of a pair:
over both :: (a -> b) -> (a, a) -> (b, b)
over both = \f t -> (f (fst t), f (snd t))
Using over _2 as a replacement for second:
over _2 show (10,20)(10,"20")
to creates a getter from any function:
a ^. to f = f a
It's most useful in chains, because it lets you mix lenses and ordinary functions. Suppose you have a record which comes from some third-party library and doesn't have any lens accessors. You want to do something like this:
value ^. _1 . field . at 2
However, field isn't a getter, and you have to do this instead:
field (value ^. _1) ^. at 2
but now value is in the middle and it's hard to read the resulting code. A variant with to is prettier and more readable:
value ^. _1 . to field . at 2
preview is a synonym for (^?), generalised for MonadReader (just like view, which is a synonym for (^.)).
preview each [1..5]Just 1
view is a synonym for (^.), generalised for MonadReader (we are able to use it instead of (^.) since functions are instances of the MonadReader class):
view _1 (1, 2)1
When you're using Reader for config and your config type has lenses generated for it, most of the time you'll be using view instead of asks:
doSomething :: (MonadReader Config m) => m Int
doSomething = do
thingy <- view setting1 -- same as “asks (^. setting1)”
anotherThingy <- view setting2
...
ASetter s t a b is something that turns a function modifying a value into a function modifying a structure. If you ignore Identity (as Identity a is the same thing as a), the type is:
type ASetter s t a b = (a -> b) -> s -> t
The reason Identity is used here is for ASetter to be composable with other types, such as Lens.
Technically, if you're writing a library, you shouldn't use this type for setters you are exporting from your library; the right type to use is Setter, but it is not provided by this package (because then it'd have to depend on distributive). It's completely alright, however, to export functions which take an ASetter as an argument.
Functions that operate on getters and folds – such as (^.), (^..), (^?) – use Getter r s a (with different values of r) to describe what kind of result they need. For instance, (^.) needs the getter to be able to return a single value, and so it accepts a getter of type Getting a s a. (^..) wants the getter to gather values together, so it uses Getting (Endo [a]) s a (it could've used Getting [a] s a instead, but it's faster with Endo). The choice of r depends on what you want to do with elements you're extracting from s.
Lens s t a b is the lowest common denominator of a setter and a getter, something that has the power of both; it has a Functor constraint, and since both Const and Identity are functors, it can be used whenever a getter or a setter is needed.
ais the type of the value inside of structurebis the type of the replaced valuesis the type of the whole structuretis the type of the structure after replacingain it withb
This is a type alias for monomorphic lenses which don't change the type of the container (or of the value inside).
A SimpleGetter s a extracts a from s; so, it's the same thing as (s -> a), but you can use it in lens chains because its type looks like this:
type SimpleGetter s a =
forall r. (a -> Const r a) -> s -> Const r s
Since Const r is a functor, SimpleGetter has the same shape as other lens types and can be composed with them. To get (s -> a) out of a SimpleGetter, choose r ~ a and feed Const :: a -> Const a a to the getter:
-- the actual signature is more permissive:
-- view :: Getting a s a -> s -> a
view :: SimpleGetter s a -> s -> a
view getter = getConst . getter Const
The actual Getter from lens is more general:
type Getter s a =
forall f. (Contravariant f, Functor f) => (a -> f a) -> s -> f s
I'm not currently aware of any functions that take lens's Getter but won't accept SimpleGetter, but you should try to avoid exporting SimpleGetters anyway to minimise confusion. Alternatively, look at microlens-contra, which provides a fully lens-compatible Getter.
Lens users: you can convert a SimpleGetter to Getter by applying to . view to it.
Concurrency
7 declarationsA ThreadId is an abstract type representing a handle to a thread. ThreadId is an instance of Eq, Ord and Show, where the Ord instance implements an arbitrary total ordering over ThreadIds. The Show instance lets you convert an arbitrary-valued ThreadId to string form; showing a ThreadId value is occasionally useful when debugging or diagnosing the behaviour of a concurrent program.
Note: in GHC, if you have a ThreadId, you essentially have a pointer to the thread itself. This means the thread itself can't be garbage collected until you drop the ThreadId. This misfeature would be difficult to correct while continuing to support threadStatus.
Instances5Eq, Ord, Show, NFData, Hashable
Eq ThreadIdDefined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncOrd ThreadIdDefined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncShow ThreadIdDefined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncNFData ThreadIdDefined in deepseq-1.5.1.0 · Control.DeepSeqHashable ThreadIdDefined in hashable-1.5.1.0 · Data.Hashable.Class
Lifted version of myThreadId.
Lifted version of isCurrentThreadBound.
Lifted version of threadWaitRead.
Lifted version of threadWaitWrite.
Lifted version of threadDelay.
Async
A version of poll that can be used inside an STM transaction.
A version of waitAnyCatch that can be used inside an STM transaction.
A version of waitAny that can be used inside an STM transaction.
A version of waitBoth that can be used inside an STM transaction.
A version of waitCatch that can be used inside an STM transaction.
A version of waitEitherCatch that can be used inside an STM transaction.
A version of waitEither that can be used inside an STM transaction.
A version of waitEither_ that can be used inside an STM transaction.
A version of wait that can be used inside an STM transaction.
Unlifted async.
Unlifted asyncBound.
Unlifted asyncOn.
Unlifted asyncOnWithUnmask.
Unlifted asyncWithUnmask.
Lifted cancel.
Lifted cancelWith. Additionally uses toAsyncException to ensure async exception safety.
Construct a value of type Conc from an action. Compose these values using the typeclass instances (most commonly Applicative and Alternative) and then run with runConc.
Unlifted concurrently.
Unlifted concurrently_.
Similar to mapConcurrently but with arguments flipped
Similar to mapConcurrently_ but with arguments flipped
Lifted link.
Lifted link2.
Executes a Traversable container of items concurrently, it uses the Flat type internally.
Executes a Traversable container of items concurrently, it uses the Flat type internally. This function ignores the results.
Lifted poll.
Similar to pooledForConcurrentlyN but with number of threads set from getNumCapabilities. Usually this is useful for CPU bound tasks.
pooledForConcurrentlyN :: (MonadUnliftIO m, Traversable t)=> IntMax. number of threads. Should not be less than 1.
-> t a-> (a -> m b)-> m (t b)
Similar to pooledMapConcurrentlyN but with flipped arguments.
pooledForConcurrentlyN_ :: (MonadUnliftIO m, Foldable t)=> IntMax. number of threads. Should not be less than 1.
-> t a-> (a -> m b)-> m ()
Like pooledMapConcurrentlyN_ but with flipped arguments.
Like pooledMapConcurrently_ but with flipped arguments.
Similar to pooledMapConcurrentlyN but with number of threads set from getNumCapabilities. Usually this is useful for CPU bound tasks.
pooledMapConcurrentlyN :: (MonadUnliftIO m, Traversable t)=> IntMax. number of threads. Should not be less than 1.
-> (a -> m b)-> t a-> m (t b)
Like mapConcurrently from async, but instead of one thread per element, it does pooling from a set of threads. This is useful in scenarios where resource consumption is bounded and for use cases where too many concurrent tasks aren't allowed.
Example usage
import Say
action :: Int -> IO Int
action n = do
tid <- myThreadId
sayString $ show tid
threadDelay (2 * 10^6) -- 2 seconds
return n
main :: IO ()
main = do
yx <- pooledMapConcurrentlyN 5 (\x -> action x) [1..5]
print yx
On executing you can see that five threads have been spawned:
$ ./pool
ThreadId 36
ThreadId 38
ThreadId 40
ThreadId 42
ThreadId 44
[1,2,3,4,5]
Let's modify the above program such that there are less threads than the number of items in the list:
import Say
action :: Int -> IO Int
action n = do
tid <- myThreadId
sayString $ show tid
threadDelay (2 * 10^6) -- 2 seconds
return n
main :: IO ()
main = do
yx <- pooledMapConcurrentlyN 3 (\x -> action x) [1..5]
print yx
On executing you can see that only three threads are active totally:
$ ./pool
ThreadId 35
ThreadId 37
ThreadId 39
ThreadId 35
ThreadId 39
[1,2,3,4,5]
pooledMapConcurrentlyN_ :: (MonadUnliftIO m, Foldable f)=> IntMax. number of threads. Should not be less than 1.
-> (a -> m b)-> f a-> m ()
Like pooledMapConcurrentlyN but with the return value discarded.
Like pooledMapConcurrently but with the return value discarded.
pooledReplicateConcurrently :: MonadUnliftIO m=> IntNumber of times to perform the action.
-> m a-> m [a]
Similar to pooledReplicateConcurrentlyN but with number of threads set from getNumCapabilities. Usually this is useful for CPU bound tasks.
pooledReplicateConcurrentlyN :: MonadUnliftIO m=> IntMax. number of threads. Should not be less than 1.
-> IntNumber of times to perform the action.
-> m a-> m [a]
Pooled version of replicateConcurrently. Performs the action in the pooled threads.
pooledReplicateConcurrentlyN_ :: MonadUnliftIO m=> IntMax. number of threads. Should not be less than 1.
-> IntNumber of times to perform the action.
-> m a-> m ()
Pooled version of replicateConcurrently_. Performs the action in the pooled threads.
pooledReplicateConcurrently_ :: MonadUnliftIO m=> IntNumber of times to perform the action.
-> m a-> m ()
Similar to pooledReplicateConcurrently_ but with number of threads set from getNumCapabilities. Usually this is useful for CPU bound tasks.
Unlifted race.
Unlifted race_.
Unlifted replicateConcurrently.
Unlifted replicateConcurrently_.
Run a Conc value on multiple threads.
Lifted uninterruptibleCancel.
Lifted wait.
Lifted waitAny.
Lifted waitAnyCancel.
Lifted waitAnyCatch.
Lifted waitAnyCatchCancel.
Lifted waitBoth.
Lifted waitCatch.
Lifted waitEither.
Lifted waitEitherCancel.
Lifted waitEitherCatch.
Lifted waitEitherCatchCancel.
Lifted waitEither_.
Unlifted withAsync.
Unlifted withAsyncBound.
Unlifted withAsyncOn.
Unlifted A.withAsyncOnWithMask.
Unlifted withAsyncWithUnmask.
Instances4Functor, Eq, Ord, Hashable
The exception thrown by cancel to terminate a thread.
Instances3Eq, Show, Exception
Eq AsyncCancelledDefined in async-2.2.6 · Control.Concurrent.Async.InternalShow AsyncCancelledDefined in async-2.2.6 · Control.Concurrent.Async.InternalException AsyncCancelledDefined in async-2.2.6 · Control.Concurrent.Async.Internal
A more efficient alternative to Concurrently, which reduces the
number of threads that need to be forked. For more information, see
this blog post.
This is provided as a separate type to Concurrently as it has a slightly different API.
Use the conc function to construct values of type Conc, and
runConc to execute the composed actions. You can use the
Applicative instance to run different actions and wait for all of
them to complete, or the Alternative instance to wait for the
first thread to complete.
In the event of a runtime exception thrown by any of the children threads, or an asynchronous exception received in the parent thread, all threads will be killed with an AsyncCancelled exception and the original exception rethrown. If multiple exceptions are generated by different threads, there are no guarantees on which exception will end up getting rethrown.
For many common use cases, you may prefer using helper functions in this module like mapConcurrently.
There are some intentional differences in behavior to
Concurrently:
Children threads are always launched in an unmasked state, not the inherited state of the parent thread.
Note that it is a programmer error to use the Alternative
instance in such a way that there are no alternatives to an empty,
e.g. runConc (empty | empty). In such a case, a ConcException
will be thrown. If there was an Alternative in the standard
libraries without empty, this library would use it instead.
Instances5Functor, Applicative, Alternative, Semigroup, Monoid
Functor m => Functor (Conc m)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncMonadUnliftIO m => Applicative (Conc m)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncMonadUnliftIO m => Alternative (Conc m)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.Async(MonadUnliftIO m, Semigroup a) => Semigroup (Conc m a)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.Async(Monoid a, MonadUnliftIO m) => Monoid (Conc m a)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.Async
Things that can go wrong in the structure of a Conc. These are programmer errors.
Instances6Eq, Ord, Show, Generic, Exception, Rep
Eq ConcExceptionDefined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncOrd ConcExceptionDefined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncShow ConcExceptionDefined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncGeneric ConcExceptionDefined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncException ConcExceptionDefined in unliftio-0.2.25.1 · UnliftIO.Internals.Asynctype Rep ConcException = D1 ('MetaDataDefined in unliftio-0.2.25.1 · UnliftIO.Internals.Async"ConcException"
"UnliftIO.Internals.Async"
"unliftio-0.2.25.1-A8fosjdyeUL4KmU9Xr8dCt"
'False) (C1 ('MetaCons"EmptyWithNoAlternative"
'PrefixI 'False) U1)
Unlifted Concurrently.
Constructors
ConcurrentlyrunConcurrently :: m a
Instances5Functor, Applicative, Alternative, Semigroup, Monoid
Monad m => Functor (Concurrently m)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncMonadUnliftIO m => Applicative (Concurrently m)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncMonadUnliftIO m => Alternative (Concurrently m)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncComposing two unlifted Concurrently values using Alternative is the equivalent to using a race combinator, the asynchrounous sub-routine that returns a value first is the one that gets it's value returned, the slowest sub-routine gets cancelled and it's thread is killed.
(MonadUnliftIO m, Semigroup a) => Semigroup (Concurrently m a)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncOnly defined by
asyncforbase >= 4.9.(Semigroup a, Monoid a, MonadUnliftIO m) => Monoid (Concurrently m a)Defined in unliftio-0.2.25.1 · UnliftIO.Internals.Async
STM
Create a new TVar holding a value supplied
Return the current value stored in a TVar.
Write the supplied value into a TVar.
Efficiently read the entire contents of a TBQueue into a list. This function never retries.
Return the length of a TBQueue.
Builds and returns a new instance of TBQueue.
Get the next value from the TBQueue without removing it,
retrying if the channel is empty.
Read the next value from the TBQueue.
A version of peekTBQueue which does not retry. Instead it
returns Nothing if no value is available.
A version of readTBQueue which does not retry. Instead it
returns Nothing if no value is available.
Put a data item back onto a channel, where it will be the next item read. Blocks if the queue is full.
Write a value to a TBQueue; blocks if the queue is full.
Clone a TChan: similar to dupTChan, but the cloned channel starts with the same content available as the original channel.
Duplicate a TChan: the duplicate channel begins empty, but data written to either channel from then on will be available from both. Hence this creates a kind of broadcast channel, where data written by anyone is seen by everyone else.
Create a write-only TChan. More precisely, readTChan will retry even after items have been written to the channel. The only way to read a broadcast channel is to duplicate it with dupTChan.
Consider a server that broadcasts messages to clients:
serve :: TChan Message -> Client -> IO loop
serve broadcastChan client = do
myChan <- dupTChan broadcastChan
forever $ do
message <- readTChan myChan
send client messageThe problem with using newTChan to create the broadcast channel is that if it is only written to and never read, items will pile up in memory. By using newBroadcastTChan to create the broadcast channel, items can be garbage collected after clients have seen them.
Build and return a new instance of TChan
Get the next value from the TChan without removing it,
retrying if the channel is empty.
Read the next value from the TChan.
A version of peekTChan which does not retry. Instead it
returns Nothing if no value is available.
A version of readTChan which does not retry. Instead it
returns Nothing if no value is available.
Put a data item back onto a channel, where it will be the next item read.
Write a value to a TChan.
Check whether a given TMVar is empty.
Create a TMVar which is initially empty.
Create a TMVar which contains the supplied value.
Swap the contents of a TMVar for a new value.
A version of readTMVar which does not retry. Instead it
returns Nothing if no value is available.
A version of takeTMVar that does not retry. The tryTakeTMVar
function returns Nothing if the TMVar was empty, or Just a if
the TMVar was full with contents a. After tryTakeTMVar, the
TMVar is left empty.
Non-blocking write of a new value to a TMVar Puts if empty. Replaces if populated.
Build and returns a new instance of TQueue
Get the next value from the TQueue without removing it,
retrying if the channel is empty.
Read the next value from the TQueue.
A version of peekTQueue which does not retry. Instead it
returns Nothing if no value is available.
A version of readTQueue which does not retry. Instead it
returns Nothing if no value is available.
Put a data item back onto a channel, where it will be the next item read.
Write a value to a TQueue.
Mutate the contents of a TVar. N.B., this version is non-strict.
Strict version of modifyTVar.
Like modifyTVar' but the function is a simple state transition that can return a side value which is passed on as the result of the STM.
Swap the contents of a TVar for a new value.
Lifted version of atomically
Renamed check for unqualified export
Lifted version of mkWeakTMVar
Lifted version of mkWeakTVar
Lifted version of newBroadcastTChanIO
Lifted version of newEmptyTMVarIO
Lifted version of newTBQueueIO
Lifted version of newTChanIO
Lifted version of newTMVarIO
Lifted version of newTQueueIO
Lifted version of newTVarIO
Lifted version of readTVarIO
Lifted version of registerDelay
Renamed retry for unqualified export
A monad supporting atomic memory transactions.
Instances11Monad, Functor, MonadFix, Applicative, Alternative, MonadPlus, …
Monad STMDefined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncFunctor STMDefined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncMonadFix STMDefined in stm-2.5.3.1 · Control.Monad.STM · orphanApplicative STMDefined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncAlternative STMDefined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncMonadPlus STMDefined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncMonadCatch STMDefined in exceptions-0.10.11 · Control.Monad.CatchMonadThrow STMDefined in exceptions-0.10.11 · Control.Monad.CatchMArray TArray e STMDefined in stm-2.5.3.1 · Control.Concurrent.STM.TArraySemigroup a => Semigroup (STM a)Defined in ghc-internal-9.1401.0 · GHC.Internal.Conc.SyncMonoid a => Monoid (STM a)Defined in ghc-internal-9.1401.0 · GHC.Internal.Conc.Sync
Shared memory locations that support atomic memory transactions.
TBQueue is an abstract type representing a bounded FIFO channel.
TChan is an abstract type representing an unbounded FIFO channel.
A TMVar is a synchronising variable, used for communication between concurrent threads. It can be thought of as a box, which may be empty or full.
TQueue is an abstract type representing an unbounded FIFO channel.
Chan
Lifted dupChan.
Lifted getChanContents.
Lifted newChan.
Lifted readChan.
Lifted writeChan.
Lifted writeList2Chan.
Chan is an abstract type representing an unbounded FIFO channel.
Timeout
Unlifted timeout.
Exceptions
65 declarationsIf the first argument evaluates to True, then the result is the second argument. Otherwise an AssertionFailed exception is raised, containing a String with the source file and line number of the call to assert.
Assertions can normally be turned on or off with a compiler flag
(for GHC, assertions are normally on unless optimisation is turned on
with -O or the -fignore-asserts option is given). When assertions
are turned off, the first argument to assert is ignored, and the second
argument is returned as the result.
Allocate and clean up a resource safely.
For more information on motivation and usage of this function, see base's
bracket. This function has two differences from the one in base.
The first, and more obvious, is that it works on any MonadUnliftIO
instance, not just IO.
The more subtle difference is that this function will use uninterruptible masking for its cleanup handler. This is a subtle distinction, but at a high level, means that resource cleanup has more guarantees to complete. This comes at the cost that an incorrectly written cleanup function cannot be interrupted.
For more information, please see https://github.com/fpco/safe-exceptions/issues/3.
Same as bracket, but only perform the cleanup if an exception is thrown.
A variant of bracketOnError where the return value from the first computation is not required.
Catch a synchronous (but not asynchronous) exception and recover from it.
This is parameterized on the exception type. To catch all synchronous exceptions, use catchAny.
catch specialized to catch all synchronous exceptions.
catchDeep specialized to catch all synchronous exception.
Same as catch, but fully force evaluation of the result value to find all impure exceptions.
catch specialized to only catching IOExceptions.
A variant of catch that catches both synchronous and asynchronous exceptions.
WARNING: This function (and other *SyncOrAsync functions) is for advanced users. Most of the
time, you probably want to use the non-SyncOrAsync versions.
Before attempting to use this function, be familiar with the "Rules for async safe handling" section in this blog post.
Same as catches, but fully force evaluation of the result value to find all impure exceptions.
Lifted version of evaluate.
Same as fromEither, but works on an IO-wrapped Either.
Same as fromEither, but works on an m-wrapped Either.
Convert from a possibly wrapped exception.
The inverse of toAsyncException and toSyncException. When using those
functions (or functions that use them, like throwTo or throwIO),
fromException might not be sufficient because the exception might be
wrapped within SyncExceptionWrapper or AsyncExceptionWrapper.
Flipped version of catch.
Flipped version of catchAny.
Flipped version of catchAnyDeep.
Flipped version of catchDeep.
handle specialized to only catching IOExceptions.
Flipped catchJust.
A variant of handle that catches both synchronous and asynchronous exceptions.
See catchSyncOrAsync.
Generate a pure value which, when forced, will synchronously throw the given exception.
Generally it's better to avoid using this function and instead use throwIO, see https://github.com/fpco/safe-exceptions#quickstart.
Check if the given exception is asynchronous.
Check if the given exception is synchronous.
Same as mapException, except works in a monadic context.
Unlifted version of mask.
Unlifted version of mask_.
Like finally, but only call after if an exception occurs.
Evaluate the value to WHNF and catch any synchronous exceptions.
The expression may still have bottom values within it; you may instead want to use pureTryDeep.
Evaluate the value to NF and catch any synchronous exceptions.
Smart constructor for a StringException that deals with the call stack.
Synchronously throw the given exception.
Note that, if you provide an exception value which is of an asynchronous
type, it will be wrapped up in SyncExceptionWrapper. See toSyncException.
A convenience function for throwing a user error. This is useful for cases where it would be too high a burden to define your own exception type.
This throws an exception of type StringException. When GHC supports it (base 4.9 and GHC 8.0 and onward), it includes a call stack.
Throw an asynchronous exception to another thread.
Synchronously typed exceptions will be wrapped into an
AsyncExceptionWrapper, see
https://github.com/fpco/safe-exceptions#determining-sync-vs-async.
It's usually a better idea to use the UnliftIO.Async module, see https://github.com/fpco/safe-exceptions#quickstart.
Convert an exception into an asynchronous exception.
For asynchronous exceptions, this is the same as toException.
For synchronous exceptions, this will wrap up the exception with
AsyncExceptionWrapper.
Convert an exception into a synchronous exception.
For synchronous exceptions, this is the same as toException.
For asynchronous exceptions, this will wrap up the exception with
SyncExceptionWrapper.
try specialized to catch all synchronous exceptions.
tryDeep specialized to catch all synchronous exceptions.
Same as try, but fully force evaluation of the result value to find all impure exceptions.
try specialized to only catching IOExceptions.
A variant of try that takes an exception predicate to select which exceptions are caught.
A variant of try that catches both synchronous and asynchronous exceptions.
See catchSyncOrAsync.
Unlifted version of uninterruptibleMask.
Unlifted version of uninterruptibleMask_.
Like onException, but provides the handler the thrown exception.
The class Typeable allows a concrete representation of a type to be calculated.
Any type that you wish to throw or catch as an exception must be an
instance of the Exception class. The simplest case is a new exception
type directly below the root:
data MyException = ThisException | ThatException
deriving Show
instance Exception MyExceptionThe default method definitions in the Exception class do what we need
in this case. You can now throw and catch ThisException and
ThatException as exceptions:
*Main> throw ThisException `catch` \e -> putStrLn ("Caught " ++ show (e :: MyException))
Caught ThisException
In more complicated examples, you may wish to define a whole hierarchy of exceptions:
---------------------------------------------------------------------
-- Make the root exception type for all the exceptions in a compiler
data SomeCompilerException = forall e . Exception e => SomeCompilerException e
instance Show SomeCompilerException where
show (SomeCompilerException e) = show e
instance Exception SomeCompilerException
compilerExceptionToException :: Exception e => e -> SomeException
compilerExceptionToException = toException . SomeCompilerException
compilerExceptionFromException :: Exception e => SomeException -> Maybe e
compilerExceptionFromException x = do
SomeCompilerException a <- fromException x
cast a
---------------------------------------------------------------------
-- Make a subhierarchy for exceptions in the frontend of the compiler
data SomeFrontendException = forall e . Exception e => SomeFrontendException e
instance Show SomeFrontendException where
show (SomeFrontendException e) = show e
instance Exception SomeFrontendException where
toException = compilerExceptionToException
fromException = compilerExceptionFromException
frontendExceptionToException :: Exception e => e -> SomeException
frontendExceptionToException = toException . SomeFrontendException
frontendExceptionFromException :: Exception e => SomeException -> Maybe e
frontendExceptionFromException x = do
SomeFrontendException a <- fromException x
cast a
---------------------------------------------------------------------
-- Make an exception type for a particular frontend compiler exception
data MismatchedParentheses = MismatchedParentheses
deriving Show
instance Exception MismatchedParentheses where
toException = frontendExceptionToException
fromException = frontendExceptionFromExceptionWe can now catch a MismatchedParentheses exception as
MismatchedParentheses, SomeFrontendException or
SomeCompilerException, but not other types, e.g. IOException:
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: MismatchedParentheses))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeFrontendException))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeCompilerException))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: IOException))
*** Exception: MismatchedParentheses
Methods
toException :: e -> SomeExceptiontoExceptionshould produce a SomeException with no attached ExceptionContext.fromException :: SomeException -> Maybe edisplayException :: e -> StringRender this exception value in a human-friendly manner.
Default implementation:
show.backtraceDesired :: e -> Bool
Instances44Exception, …
Exception AsyncCancelledDefined in async-2.2.6 · Control.Concurrent.Async.InternalException ExceptionInLinkedThreadDefined in async-2.2.6 · Control.Concurrent.Async.InternalException WardenExceptionDefined in async-2.2.6 · Control.Concurrent.Async.WardenException TimeoutDefined in base-4.22.0.0 · System.TimeoutException SizeOverflowExceptionDefined in bytestring-0.12.2.0 · Data.ByteString.Internal.TypeException VoidDefined in ghc-internal-9.1401.0 · GHC.Internal.Exception.TypeException NestedAtomicallyDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException NoMatchingContinuationPromptDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException NoMethodErrorDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException NonTerminationDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException PatternMatchFailDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException RecConErrorDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException RecSelErrorDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException RecUpdErrorDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException TypeErrorDefined in ghc-internal-9.1401.0 · GHC.Internal.Control.Exception.BaseException DynamicDefined in ghc-internal-9.1401.0 · GHC.Internal.Data.DynamicException ErrorCallDefined in ghc-internal-9.1401.0 · GHC.Internal.ExceptionException ArithExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.Exception.TypeException SomeExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.Exception.TypeThis drops any attached ExceptionContext.
Exception AllocationLimitExceededDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException ArrayExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException AssertionFailedDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException AsyncExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException BlockedIndefinitelyOnMVarDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException BlockedIndefinitelyOnSTMDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException CompactionFailedDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException DeadlockDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException ExitCodeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException FixIOExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException IOExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException SomeAsyncExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException FileLockingNotSupportedDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.Handle.Lock.CommonException EncodingExceptionDefined in os-string-2.0.8 · System.OsString.Encoding.InternalException ProcessExceptionDefined in rio-0.1.25.0 · RIO.ProcessException AsyncExceptionWrapperDefined in safe-exceptions-0.1.7.4 · Control.Exception.SafeException StringExceptionDefined in safe-exceptions-0.1.7.4 · Control.Exception.SafeException SyncExceptionWrapperDefined in safe-exceptions-0.1.7.4 · Control.Exception.SafeException UnicodeExceptionDefined in text-2.1.3 · Data.Text.Encoding.ErrorException ByteStringOutputExceptionDefined in typed-process-0.2.13.0 · System.Process.Typed.InternalException ExitCodeExceptionDefined in typed-process-0.2.13.0 · System.Process.Typed.InternalException StringExceptionDefined in unliftio-0.2.25.1 · UnliftIO.ExceptionException ConcExceptionDefined in unliftio-0.2.25.1 · UnliftIO.Internals.AsyncException a => Exception (ExceptionWithContext a)Defined in ghc-internal-9.1401.0 · GHC.Internal.Exception.TypeException e => Exception (NoBacktrace e)Defined in ghc-internal-9.1401.0 · GHC.Internal.Exception.Type
The SomeException type is the root of the exception type hierarchy.
When an exception of type e is thrown, behind the scenes it is
encapsulated in a SomeException.
Constructors
forall e. (Exception e, HasExceptionContext) => SomeException e
Instances3Show, Exception, Display
Show SomeExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.Exception.TypeException SomeExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.Exception.TypeThis drops any attached ExceptionContext.
Display SomeExceptionDefined in rio-0.1.25.0 · RIO.Prelude.Display
Exceptions that occur in the IO monad.
An IOException records a more specific error type, a descriptive
string and maybe the handle that was used when the error was
flagged.
Instances5Eq, Show, Exception, Display, MonadError
Eq IOExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionShow IOExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException IOExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionDisplay IOExceptionDefined in rio-0.1.25.0 · RIO.Prelude.DisplayMonadError IOException IODefined in mtl-2.3.1 · Control.Monad.Error.Class
Superclass for asynchronous exceptions.
Constructors
forall e. Exception e => SomeAsyncException e
Instances2Show, Exception
Show SomeAsyncExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException SomeAsyncExceptionDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.Exception
Wrap up a synchronous exception to be treated as an asynchronous exception
This is intended to be created via toAsyncException
Constructors
forall e. Exception e => AsyncExceptionWrapper e
Instances2Show, Exception
Show AsyncExceptionWrapperDefined in safe-exceptions-0.1.7.4 · Control.Exception.SafeException AsyncExceptionWrapperDefined in safe-exceptions-0.1.7.4 · Control.Exception.Safe
Wrap up an asynchronous exception to be treated as a synchronous exception
This is intended to be created via toSyncException
Constructors
forall e. Exception e => SyncExceptionWrapper e
Instances2Show, Exception
Show SyncExceptionWrapperDefined in safe-exceptions-0.1.7.4 · Control.Exception.SafeException SyncExceptionWrapperDefined in safe-exceptions-0.1.7.4 · Control.Exception.Safe
Exception type thrown by throwString.
Note that the second field of the data constructor depends on GHC/base version. For base 4.9 and GHC 8.0 and later, the second field is a call stack. Previous versions of GHC and base do not support call stacks, and the field is simply unit (provided to make pattern matching across GHC versions easier).
Constructors
Instances3Eq, Show, Exception
Eq StringExceptionDefined in unliftio-0.2.25.1 · UnliftIO.ExceptionShow StringExceptionDefined in unliftio-0.2.25.1 · UnliftIO.ExceptionException StringExceptionDefined in unliftio-0.2.25.1 · UnliftIO.Exception
Re-exported from Control.Monad.Catch:
Throw an exception. Note that this throws when this action is run in
the monad m, not when it is applied. It is a generalization of
Control.Exception's throwIO.
Should satisfy the law:
throwM e >> f = throwM eFiles and handles
41 declarationsstderr is a handle managing the programs standard error.
stdin is a handle managing the programs standard input.
stdout is a handle managing the programs standard output.
Get the number of seconds which have passed since an arbitrary starting time, useful for calculating runtime in a program.
Lifted version of hClose
Lifted version of hFileSize
Lifted version of hFlush
Lifted version of hGetBuffering
Lifted version of hGetEcho
Lifted version of hIsClosed
Lifted version of hIsEOF
Lifted version of hIsOpen
Lifted version of hIsReadable
Lifted version of hIsSeekable
Lifted version of hIsTerminalDevice
Lifted version of hIsWritable
Lifted version of hReady
Lifted version of hSeek
Lifted version of hSetBuffering
Lifted version of hSetEcho
Lifted version of hSetFileSize
Lifted version of hTell
Lifted version of hWaitForInput
Lifted version of openFile
Unlifted version of withBinaryFile.
Unlifted version of withFile.
A mode that determines the effect of GHC.Internal.System.IO.hSeek hdl mode i.
Constructors
AbsoluteSeekthe position of
hdlis set toi.RelativeSeekthe position of
hdlis set to offsetifrom the current position.SeekFromEndthe position of
hdlis set to offsetifrom the end of the file.
Instances6Enum, Eq, Ord, Read, Show, Ix
Enum SeekModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.DeviceEq SeekModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.DeviceOrd SeekModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.DeviceRead SeekModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.DeviceShow SeekModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.DeviceIx SeekModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.Device
Three kinds of buffering are supported: line-buffering, block-buffering or no-buffering. These modes have the following effects. For output, items are written out, or flushed, from the internal buffer according to the buffer mode:
line-buffering: the entire output buffer is flushed whenever a newline is output, the buffer overflows, a
GHC.Internal.System.IO.hFlushis issued, or the handle is closed.block-buffering: the entire buffer is written out whenever it overflows, a
GHC.Internal.System.IO.hFlushis issued, or the handle is closed.no-buffering: output is written immediately, and never stored in the buffer.
An implementation is free to flush the buffer more frequently, but not less frequently, than specified above. The output buffer is emptied as soon as it has been written out.
Similarly, input occurs according to the buffer mode for the handle:
line-buffering: when the buffer for the handle is not empty, the next item is obtained from the buffer; otherwise, when the buffer is empty, characters up to and including the next newline character are read into the buffer. No characters are available until the newline character is available or the buffer is full.
block-buffering: when the buffer for the handle becomes empty, the next block of data is read into the buffer.
no-buffering: the next input item is read and returned. The
GHC.Internal.System.IO.hLookAheadoperation implies that even a no-buffered handle may require a one-character buffer.
The default buffering mode when a handle is opened is implementation-dependent and may depend on the file system object which is attached to that handle. For most implementations, physical files will normally be block-buffered and terminals will normally be line-buffered.
Constructors
NoBufferingbuffering is disabled if possible.
LineBufferingline-buffering should be enabled if possible.
BlockBuffering (Maybe Int)block-buffering should be enabled if possible. The size of the buffer is
nitems if the argument is Justnand is otherwise implementation-dependent.
Instances4Eq, Ord, Read, Show
Eq BufferModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.Handle.TypesOrd BufferModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.Handle.TypesRead BufferModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.Handle.TypesShow BufferModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.Handle.Types
Haskell defines operations to read and write characters from and to files,
represented by values of type Handle. Each value of this type is a
handle: a record used by the Haskell run-time system to manage I/O
with file system objects. A handle has at least the following properties:
whether it manages input or output or both;
whether it is open, closed or semi-closed;
whether the object is seekable;
whether buffering is disabled, or enabled on a line or block basis;
a buffer (whose length may be zero).
Most handles will also have a current I/O position indicating where the next input or output operation will occur. A handle is readable if it manages only input or both input and output; likewise, it is writable if it manages only output or both input and output. A handle is open when first allocated. Once it is closed it can no longer be used for either input or output, though an implementation cannot re-use its storage while references remain to it. Handles are in the Show and Eq classes. The string produced by showing a handle is system dependent; it should include enough information to identify the handle for debugging. A handle is equal according to == only to itself; no attempt is made to compare the internal state of different handles for equality.
See GHC.Internal.System.IO.openFile
Instances6Enum, Eq, Ord, Read, Show, Ix
Enum IOModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.IOModeEq IOModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.IOModeOrd IOModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.IOModeRead IOModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.IOModeShow IOModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.IOModeIx IOModeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.IOMode
withSystemTempDirectory :: MonadUnliftIO m=> StringDirectory name template. See openTempFile.
-> (FilePath -> m a)Callback that can use the directory.
-> m a
Create and use a temporary directory in the system standard temporary directory.
Behaves exactly the same as withTempDirectory, except that the parent temporary directory
will be that returned by getCanonicalTemporaryDirectory.
withSystemTempFile :: MonadUnliftIO m=> StringFile name template. See openTempFile.
-> (FilePath -> Handle -> m a)Callback that can use the file
-> m a
Create and use a temporary file in the system standard temporary directory.
Behaves exactly the same as withTempFile, except that the parent temporary directory
will be that returned by getCanonicalTemporaryDirectory.
withTempDirectory :: MonadUnliftIO m=> FilePathTemp directory to create the directory in.
-> StringDirectory name template. See openTempFile.
-> (FilePath -> m a)Callback that can use the directory.
-> m a
Create and use a temporary directory.
Creates a new temporary directory inside the given directory, making use of the template. The temp directory is deleted after use. For example:
withTempDirectory "src" "sdist." $ \tmpDir -> do ...The tmpDir will be a new subdirectory of the given directory, e.g.
src/sdist.342.
withTempFile :: MonadUnliftIO m=> FilePathTemp dir to create the file in.
-> StringFile name template. See openTempFile.
-> (FilePath -> Handle -> m a)Callback that can use the file.
-> m a
Use a temporary filename that doesn't already exist.
Creates a new temporary file inside the given directory, making use of the template. The temp file is deleted after use. For example:
withTempFile "src" "sdist." $ \tmpFile hFile -> do ...The tmpFile will be file in the given directory, e.g.
src/sdist.342.
Read a file in UTF8 encoding, throwing an exception on invalid character encoding.
This function will use OS-specific line ending handling.
Lazily get the contents of a file. Unlike readFile, this ensures that if an exception is thrown, the file handle is closed immediately.
Lazily read a file in UTF8 encoding.
Write a file in UTF8 encoding
This function will use OS-specific line ending handling.
Exit
4 declarationsLifted version of "System.Exit.exitFailure".
@since 0.1.9.0.
Lifted version of "System.Exit.exitSuccess".
@since 0.1.9.0.
Lifted version of "System.Exit.exitWith".
@since 0.1.9.0.
Defines the exit codes that a program can return.
Constructors
ExitSuccessindicates successful termination;
ExitFailure Intindicates program failure with an exit code. The exact interpretation of the code is operating-system dependent. In particular, some values may be prohibited (e.g. 0 on a POSIX-compliant system).
Instances8Eq, Ord, Read, Show, Generic, Exception, …
Eq ExitCodeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionOrd ExitCodeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionRead ExitCodeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionShow ExitCodeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionGeneric ExitCodeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionException ExitCodeDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.ExceptionNFData ExitCodeDefined in deepseq-1.5.1.0 · Control.DeepSeqtype Rep ExitCode = D1 ('MetaDataDefined in ghc-internal-9.1401.0 · GHC.Internal.IO.Exception"ExitCode"
"GHC.Internal.IO.Exception"
"ghc-internal"
'False) (C1 ('MetaCons"ExitSuccess"
'PrefixI 'False) U1 :+: C1 ('MetaCons"ExitFailure"
'PrefixI 'False) (S1 ('MetaSel 'Nothing 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int)))
Mutable Variables
0 declarationsSomeRef
Lift one RIO env to another.
Modify a SomeRef This function is subject to change due to the lack of atomic operations
create a new boxed SomeRef
create a new unboxed SomeRef
Read from a SomeRef
Write to a SomeRef
Instances1HasStateRef
HasStateRef a (SomeRef a)Defined in rio-0.1.25.0 · RIO.Prelude.RIOIdentity state reference where the SomeRef is the env
Instances1HasWriteRef
HasWriteRef a (SomeRef a)Defined in rio-0.1.25.0 · RIO.Prelude.RIOIdentity write reference where the SomeRef is the env
Abstraction over how to read from and write to a mutable reference
Instances2HasStateRef, HasWriteRef
HasStateRef a (SomeRef a)Defined in rio-0.1.25.0 · RIO.Prelude.RIOIdentity state reference where the SomeRef is the env
HasWriteRef a (SomeRef a)Defined in rio-0.1.25.0 · RIO.Prelude.RIOIdentity write reference where the SomeRef is the env
URef
Modify a value in a URef. Note that this action is strict, and will force evaluation of the result value.
Create a new URef
Read the value in a URef
Write a value into a URef. Note that this action is strict, and will force evalution of the value.
An unboxed reference. This works like an IORef, but the data is stored in a bytearray instead of a heap object, avoiding significant allocation overhead in some cases. For a concrete example, see this Stack Overflow question: https://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes.
The first parameter is the state token type, the same as would be used for the ST monad. If you're using an IO-based monad, you can use the convenience IOURef type synonym instead.
IORef
Lifted atomicModifyIORef.
Lifted atomicModifyIORef'.
Lifted atomicWriteIORef.
Unlifted mkWeakIORef.
Lifted modifyIORef.
Lifted modifyIORef'.
Lifted newIORef.
Lifted readIORef.
Lifted writeIORef.
MVar
Lifted isEmptyMVar.
Unlifted mkWeakMVar.
Unlifted modifyMVar.
Unlifted modifyMVarMasked.
Unlifted modifyMVarMasked_.
Unlifted modifyMVar_.
Lifted newEmptyMVar.
Lifted newMVar.
Lifted putMVar.
Lifted readMVar.
Lifted swapMVar.
Lifted takeMVar.
Lifted tryPutMVar.
Lifted tryReadMVar.
Lifted tryTakeMVar.
Unlifted withMVar.
Unlifted withMVarMasked.
An MVar (pronounced "em-var") is a synchronising variable, used for communication between concurrent threads. It can be thought of as a box, which may be empty or full.
Instances3NFData1, Eq, NFData
QSem
Lifted newQSem.
Lifted signalQSem.
Lifted waitQSem.
withQSem is an exception-safe wrapper for performing the provided operation while holding a unit of value from the semaphore. It ensures the semaphore cannot be leaked if there are exceptions.
QSemN
Lifted newQSemN.
Lifted signalQSemN.
Lifted waitQSemN.
withQSemN is an exception-safe wrapper for performing the provided operation while holding N unit of value from the semaphore. It ensures the semaphore cannot be leaked if there are exceptions.
Memoize
Same as memoizeRef, but uses an MVar to ensure that an action is only run once, even in a multithreaded application.
Create a new Memoized value using an IORef under the surface. Note that the action may be run in multiple threads simultaneously, so this may not be thread safe (depending on the underlying action). Consider using memoizeMVar.
Extract a value from a Memoized, running an action if no cached value is available.
A "run once" value, with results saved. Extract the value with runMemoized. For single-threaded usage, you can use memoizeRef to create a value. If you need guarantees that only one thread will run the action at a time, use memoizeMVar.
Note that this type provides a Show instance for convenience, but not useful information can be provided.
Deque
module RIO.Deque
Debugging
27 declarationsTrace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code
Trace statement left in code