| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Control.Monad.Logger.Aeson
Synopsis
- data Message = Text :# [SeriesElem]
- data SeriesElem
- data LoggedMessage = LoggedMessage {}
- logDebug :: (HasCallStack, MonadLogger m) => Message -> m ()
- logInfo :: (HasCallStack, MonadLogger m) => Message -> m ()
- logWarn :: (HasCallStack, MonadLogger m) => Message -> m ()
- logError :: (HasCallStack, MonadLogger m) => Message -> m ()
- logOther :: (HasCallStack, MonadLogger m) => LogLevel -> Message -> m ()
- logDebugCS :: MonadLogger m => CallStack -> Message -> m ()
- logInfoCS :: MonadLogger m => CallStack -> Message -> m ()
- logWarnCS :: MonadLogger m => CallStack -> Message -> m ()
- logErrorCS :: MonadLogger m => CallStack -> Message -> m ()
- logOtherCS :: MonadLogger m => CallStack -> LogLevel -> Message -> m ()
- logDebugNS :: (HasCallStack, MonadLogger m) => LogSource -> Message -> m ()
- logInfoNS :: (HasCallStack, MonadLogger m) => LogSource -> Message -> m ()
- logWarnNS :: (HasCallStack, MonadLogger m) => LogSource -> Message -> m ()
- logErrorNS :: (HasCallStack, MonadLogger m) => LogSource -> Message -> m ()
- logOtherNS :: (HasCallStack, MonadLogger m) => LogSource -> LogLevel -> Message -> m ()
- logDebugN :: (HasCallStack, MonadLogger m) => Message -> m ()
- logInfoN :: (HasCallStack, MonadLogger m) => Message -> m ()
- logWarnN :: (HasCallStack, MonadLogger m) => Message -> m ()
- logErrorN :: (HasCallStack, MonadLogger m) => Message -> m ()
- logOtherN :: (HasCallStack, MonadLogger m) => LogLevel -> Message -> m ()
- withThreadContext :: (MonadIO m, MonadMask m) => [Pair] -> m a -> m a
- myThreadContext :: (MonadIO m, MonadThrow m) => m (KeyMap Value)
- runFileLoggingT :: (MonadIO m, MonadMask m) => FilePath -> LoggingT m a -> m a
- runHandleLoggingT :: (LogLevel -> Handle) -> LoggingT m a -> m a
- runStdoutLoggingT :: LoggingT m a -> m a
- runStderrLoggingT :: LoggingT m a -> m a
- runFastLoggingT :: LoggerSet -> LoggingT m a -> m a
- defaultOutput :: Handle -> Loc -> LogSource -> LogLevel -> LogStr -> IO ()
- handleOutput :: (LogLevel -> Handle) -> Loc -> LogSource -> LogLevel -> LogStr -> IO ()
- fastLoggerOutput :: LoggerSet -> Loc -> LogSource -> LogLevel -> LogStr -> IO ()
- defaultOutputWith :: OutputOptions -> Loc -> LogSource -> LogLevel -> LogStr -> IO ()
- defaultOutputOptions :: (LogLevel -> ByteString -> IO ()) -> OutputOptions
- data OutputOptions
- outputIncludeThreadId :: OutputOptions -> Bool
- outputBaseThreadContext :: OutputOptions -> [Pair]
- defaultLogStr :: UTCTime -> KeyMap Value -> Loc -> LogSource -> LogLevel -> LogStr -> LogStr
- defaultHandleFromLevel :: (Text -> Handle) -> LogLevel -> Handle
- (.=) :: (KeyValue kv, ToJSON v) => Key -> v -> kv
- fromLogStr :: LogStr -> ByteString
- data LogStr
- class ToLogStr msg where
- defaultLoc :: Loc
- mapNoLoggingT :: (m a -> n b) -> NoLoggingT m a -> NoLoggingT n b
- mapLoggingT :: (m a -> n b) -> LoggingT m a -> LoggingT n b
- filterLogger :: forall (m :: Type -> Type) a. (LogSource -> LogLevel -> Bool) -> LoggingT m a -> LoggingT m a
- withChannelLogger :: forall (m :: Type -> Type) a. (MonadBaseControl IO m, MonadIO m) => Int -> LoggingT m a -> LoggingT m a
- unChanLoggingT :: (MonadLogger m, MonadIO m) => Chan LogLine -> m void
- runChanLoggingT :: MonadIO m => Chan LogLine -> LoggingT m a -> m a
- execWriterLoggingT :: Functor m => WriterLoggingT m a -> m [LogLine]
- runWriterLoggingT :: Functor m => WriterLoggingT m a -> m (a, [LogLine])
- logOtherS :: Q Exp
- logErrorS :: Q Exp
- logWarnS :: Q Exp
- logInfoS :: Q Exp
- logDebugS :: Q Exp
- liftLoc :: Loc -> Q Exp
- logOtherSH :: Text -> Q Exp
- logErrorSH :: Q Exp
- logWarnSH :: Q Exp
- logInfoSH :: Q Exp
- logDebugSH :: Q Exp
- data LogLevel
- type LogSource = Text
- class Monad m => MonadLogger (m :: Type -> Type) where
- monadLoggerLog :: ToLogStr msg => Loc -> LogSource -> LogLevel -> msg -> m ()
- class (MonadLogger m, MonadIO m) => MonadLoggerIO (m :: Type -> Type) where
- newtype NoLoggingT (m :: Type -> Type) a = NoLoggingT {
- runNoLoggingT :: m a
- type LogLine = (Loc, LogSource, LogLevel, LogStr)
- newtype WriterLoggingT (m :: Type -> Type) a = WriterLoggingT {
- unWriterLoggingT :: m (a, DList LogLine)
- newtype LoggingT (m :: Type -> Type) a = LoggingT {}
- data Loc = Loc {}
Synopsis
monad-logger-aeson provides structured JSON logging using monad-logger's
interface. Specifically, it is intended to be a (largely) drop-in replacement
for monad-logger's Control.Monad.Logger.CallStack module.
In brief, this program:
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE OverloadedStrings #-}
module Main
( main
) where
import Control.Monad.Logger.Aeson
doStuff :: (MonadLogger m) => Int -> m ()
doStuff x = do
logDebug $ "Doing stuff" :# ["x" .= x]
main :: IO ()
main = do
runStdoutLoggingT do
doStuff 42
logInfo "Done"Would produce this output (formatted for readability here with jq):
{
"time": "2022-05-15T20:52:15.5559417Z",
"level": "debug",
"location": {
"package": "main",
"module": "Main",
"file": "app/readme-example.hs",
"line": 11,
"char": 3
},
"message": {
"text": "Doing stuff",
"meta": {
"x": 42
}
}
}
{
"time": "2022-05-15T20:52:15.5560448Z",
"level": "info",
"location": {
"package": "main",
"module": "Main",
"file": "app/readme-example.hs",
"line": 17,
"char": 5
},
"message": {
"text": "Done"
}
}For additional detail on the library, please see the remainder of these Haddocks and the following external resources:
Types
A Message captures a textual component and a metadata component. The
metadata component is a list of SeriesElem to support tacking on arbitrary
structured data to a log message.
With the OverloadedStrings extension enabled, Message values can be
constructed without metadata fairly conveniently, just as if we were using
Text directly:
logDebug "Some log message without metadata"
Metadata may be included in a Message via the :# constructor:
logDebug$ "Some log message with metadata":#[ "bloorp".=(42 ::Int) , "bonk".=("abc" ::Text) ]
The mnemonic for the :# constructor is that the # symbol is sometimes
referred to as a hash, a JSON object can be thought of as a hash map, and
so with :# (and enough squinting), we are cons-ing a textual message onto
a JSON object. Yes, this mnemonic isn't well-typed, but hopefully it still
helps!
Since: 0.1.0.0
Constructors
| Text :# [SeriesElem] infixr 5 |
data SeriesElem Source #
A single key-value pair, where the value is encoded JSON. This is a more
restricted version of Series: a SeriesElem is intended to encapsulate
exactly one key-value pair, whereas a Series encapsulates zero or more
key-value pairs. SeriesElem values can be created via (.=) from aeson.
While a SeriesElem most often will map to a single pair, note that a
Semigroup instance is available for performance's sake. The Semigroup
instance is useful when multiple pairs are grouped together and then shared
across multiple logging calls. In that case, the cost of combining the pairs
in the group must only be paid once.
Since: 0.3.0.0
Instances
| KeyValue SeriesElem Source # | Since: 0.3.0.0 |
Defined in Control.Monad.Logger.Aeson.Internal Methods (.=) :: ToJSON v => Key -> v -> SeriesElem # | |
| Semigroup SeriesElem Source # | Since: 0.3.1.0 |
Defined in Control.Monad.Logger.Aeson.Internal Methods (<>) :: SeriesElem -> SeriesElem -> SeriesElem # sconcat :: NonEmpty SeriesElem -> SeriesElem # stimes :: Integral b => b -> SeriesElem -> SeriesElem # | |
data LoggedMessage Source #
This type is the Haskell representation of each JSON log message produced by this library.
While we never interact with this type directly when logging messages with
monad-logger-aeson, we may wish to use this type if we are
parsing/processing log files generated by this library.
Since: 0.1.0.0
Constructors
| LoggedMessage | |
Instances
Logging functions
Implicit call stack, no LogSource
logDebug :: (HasCallStack, MonadLogger m) => Message -> m () Source #
logInfo :: (HasCallStack, MonadLogger m) => Message -> m () Source #
See logDebug
Since: 0.1.0.0
logWarn :: (HasCallStack, MonadLogger m) => Message -> m () Source #
See logDebug
Since: 0.1.0.0
logError :: (HasCallStack, MonadLogger m) => Message -> m () Source #
See logDebug
Since: 0.1.0.0
logOther :: (HasCallStack, MonadLogger m) => LogLevel -> Message -> m () Source #
See logDebug
Since: 0.1.0.0
Explicit call stack, no LogSource
logDebugCS :: MonadLogger m => CallStack -> Message -> m () Source #
logInfoCS :: MonadLogger m => CallStack -> Message -> m () Source #
See logDebugCS
Since: 0.1.0.0
logWarnCS :: MonadLogger m => CallStack -> Message -> m () Source #
See logDebugCS
Since: 0.1.0.0
logErrorCS :: MonadLogger m => CallStack -> Message -> m () Source #
See logDebugCS
Since: 0.1.0.0
logOtherCS :: MonadLogger m => CallStack -> LogLevel -> Message -> m () Source #
See logDebugCS
Since: 0.1.0.0
Implicit call stack, with LogSource
logDebugNS :: (HasCallStack, MonadLogger m) => LogSource -> Message -> m () Source #
See logDebugCS
Since: 0.1.0.0
logInfoNS :: (HasCallStack, MonadLogger m) => LogSource -> Message -> m () Source #
See logDebugNS
Since: 0.1.0.0
logWarnNS :: (HasCallStack, MonadLogger m) => LogSource -> Message -> m () Source #
See logDebugNS
Since: 0.1.0.0
logErrorNS :: (HasCallStack, MonadLogger m) => LogSource -> Message -> m () Source #
See logDebugNS
Since: 0.1.0.0
logOtherNS :: (HasCallStack, MonadLogger m) => LogSource -> LogLevel -> Message -> m () Source #
See logDebugNS
Since: 0.1.0.0
Convenience aliases
logDebugN :: (HasCallStack, MonadLogger m) => Message -> m () Source #
logInfoN :: (HasCallStack, MonadLogger m) => Message -> m () Source #
See logDebugN
Since: 0.4.0.0
logWarnN :: (HasCallStack, MonadLogger m) => Message -> m () Source #
See logDebugN
Since: 0.4.0.0
logErrorN :: (HasCallStack, MonadLogger m) => Message -> m () Source #
See logDebugN
Since: 0.4.0.0
logOtherN :: (HasCallStack, MonadLogger m) => LogLevel -> Message -> m () Source #
See logDebugN
Since: 0.4.0.0
Thread context
withThreadContext :: (MonadIO m, MonadMask m) => [Pair] -> m a -> m a Source #
This function lets us register structured, contextual info for the duration of the provided action. All messages logged within the provided action will automatically include this contextual info. This function is thread-safe, as the contextual info is scoped to the calling thread only.
This function is additive: if we nest calls to it, each nested call will add
to the existing thread context. In the case of overlapping keys, the nested
call's Pair value(s) will win. Whenever the inner action completes, the
thread context is rolled back to its value set in the enclosing action.
If we wish to include the existing thread context from one thread in another
thread, we must register the thread context explicitly on that other thread.
myThreadContext can be leveraged in this case.
Registering thread context for messages can be useful in many scenarios. One
particularly apt scenario is in wai middlewares. We can generate an ID for
each incoming request then include it in the thread context. Now all messages
subsequently logged from our endpoint handler will automatically include that
request ID:
import Control.Monad.Logger.Aeson ((.=), withThreadContext)
import Network.Wai (Middleware)
import qualified Data.UUID.V4 as UUID
addRequestId :: Middleware
addRequestId app = \request sendResponse -> do
uuid <- UUID.nextRandom
withThreadContext ["requestId" .= uuid] do
app request sendResponseIf we're coming from a Java background, it may be helpful for us to draw
parallels between this function and log4j2's ThreadContext (or perhaps
log4j's MDC). They all enable the same thing: setting some thread-local
info that will be automatically pulled into each logged message.
Since: 0.1.0.0
myThreadContext :: (MonadIO m, MonadThrow m) => m (KeyMap Value) Source #
This function lets us retrieve the calling thread's thread context. For
more detail, we can consult the docs for withThreadContext.
Note that even though the type signature lists MonadThrow as a required
constraint, the library guarantees that myThreadContext will never throw.
Since: 0.1.0.0
LoggingT runners
runFileLoggingT :: (MonadIO m, MonadMask m) => FilePath -> LoggingT m a -> m a Source #
Run a block using a MonadLogger instance which appends to the specified
file.
Note that this differs from the monad-logger version in its constraints.
We use the exceptions package's MonadMask here for bracketing, rather
than monad-control.
Since: 0.1.0.0
runHandleLoggingT :: (LogLevel -> Handle) -> LoggingT m a -> m a Source #
Run a block using a MonadLogger instance which prints to a Handle
determined by the log message's LogLevel.
A common use case for this function is to log warn/error messages to stderr
and debug/info messages to stdout in CLIs/tools (see
defaultHandleFromLevel).
Since: 0.1.0.0
runStdoutLoggingT :: LoggingT m a -> m a Source #
Run a block using a MonadLogger instance which prints to stdout.
Since: 0.1.0.0
runStderrLoggingT :: LoggingT m a -> m a Source #
Run a block using a MonadLogger instance which prints to stderr.
Since: 0.1.0.0
runFastLoggingT :: LoggerSet -> LoggingT m a -> m a Source #
Run a block using a MonadLogger instance which appends to the specified
LoggerSet.
Since: 0.1.0.0
Utilities for defining our own loggers
defaultOutput :: Handle -> Loc -> LogSource -> LogLevel -> LogStr -> IO () Source #
A default implementation of the action that backs the monadLoggerLog
function. It accepts a file handle as the first argument and will log
incoming LogStr values wrapped in the JSON structure prescribed by this
library.
This is used in the definition of runStdoutLoggingT and
runStderrLoggingT:
runStdoutLoggingT::LoggingTm a -> m arunStdoutLoggingT=fliprunLoggingT(defaultOutputstdout)
We can instead use defaultOutputWith if we need more control of the output.
Since: 0.1.0.0
handleOutput :: (LogLevel -> Handle) -> Loc -> LogSource -> LogLevel -> LogStr -> IO () Source #
An implementation of the action that backs the monadLoggerLog function,
where the Handle destination for each log message is determined by the log
message's LogLevel. This function will log incoming LogStr values wrapped
in the JSON structure prescribed by this library.
This is used in the definition of runHandleLoggingT:
runHandleLoggingT:: (LogLevel->Handle) ->LoggingTm a -> m arunHandleLoggingT=fliprunLoggingT.handleOutput
Since: 0.1.0.0
fastLoggerOutput :: LoggerSet -> Loc -> LogSource -> LogLevel -> LogStr -> IO () Source #
An implementation of the action that backs the monadLoggerLog function,
where log messages are written to a provided LoggerSet. This function will
log incoming LogStr values wrapped in the JSON structure prescribed by this
library.
This is used in the definition of runFastLoggingT:
runFastLoggingT::LoggerSet->LoggingTm a -> m arunFastLoggingTloggerSet =fliprunLoggingT(fastLoggerOutputloggerSet)
Since: 0.1.0.0
defaultOutputWith :: OutputOptions -> Loc -> LogSource -> LogLevel -> LogStr -> IO () Source #
This function is a lower-level helper for implementing the action that
backs the monadLoggerLog function.
We should generally prefer defaultOutput over this function, but this
function is available if we do need more control over our output.
Since: 0.1.0.0
defaultOutputOptions :: (LogLevel -> ByteString -> IO ()) -> OutputOptions Source #
Given an output action for log messages, this function will produce the
default recommended OutputOptions.
Specific options can be overriden via record update syntax using
outputIncludeThreadId, outputBaseThreadContext, and friends.
Since: 0.1.0.0
data OutputOptions Source #
OutputOptions is for use with
defaultOutputWith and enables us to configure
the JSON output produced by this library.
We can get a hold of a value of this type via
defaultOutputOptions.
Since: 0.1.0.0
outputIncludeThreadId :: OutputOptions -> Bool Source #
Controls whether or not the thread ID is included in each log message's thread context.
Default: False
Since: 0.1.0.0
outputBaseThreadContext :: OutputOptions -> [Pair] Source #
Allows for setting a "base" thread context, i.e. a set of Pair that
will always be present in log messages.
If we subsequently use withThreadContext to
register some thread context for our messages, if any of the keys in
those Pair values overlap with the "base" thread context, then the
overlapped Pair values in the "base" thread context will be overridden
for the duration of the action provided to
withThreadContext.
Default: mempty
Since: 0.1.0.0
defaultLogStr :: UTCTime -> KeyMap Value -> Loc -> LogSource -> LogLevel -> LogStr -> LogStr Source #
Since: 0.1.0.0
defaultHandleFromLevel :: (Text -> Handle) -> LogLevel -> Handle Source #
This function maps the possible LogLevel values to Handle values.
Specifically, LevelDebug and LevelInfo map to stdout, while LevelWarn
and LevelError map to stderr. The function is most useful for CLIs/tools
(see runHandleLoggingT).
The input function discriminating Text is used to determine the Handle
mapping for LevelOther. For example, if we wish for all LevelOther
messages to be logged to stderr, we can supply (const stderr) as the
value for this input function.
Since: 0.1.0.0
Re-exports from aeson
Re-exports from monad-logger
fromLogStr :: LogStr -> ByteString #
Converting LogStr to ByteString.
Log message builder. Use (<>) to append two LogStr in O(1).
Types that can be converted to a LogStr. Instances for
types from the text library use a UTF-8 encoding. Instances
for numerical types use a decimal encoding.
Instances
defaultLoc :: Loc #
dummy location, used with logWithoutLoc
Since: monad-logger-0.3.23
mapNoLoggingT :: (m a -> n b) -> NoLoggingT m a -> NoLoggingT n b #
Map the unwrapped computation using the given function.
Since: monad-logger-0.3.29
mapLoggingT :: (m a -> n b) -> LoggingT m a -> LoggingT n b #
Map the unwrapped computation using the given function.
Since: monad-logger-0.3.29
filterLogger :: forall (m :: Type -> Type) a. (LogSource -> LogLevel -> Bool) -> LoggingT m a -> LoggingT m a #
Only log messages passing the given predicate function.
This can be a convenient way, for example, to ignore debug level messages.
Since: monad-logger-0.3.13
Arguments
| :: forall (m :: Type -> Type) a. (MonadBaseControl IO m, MonadIO m) | |
| => Int | Number of messages to keep |
| -> LoggingT m a | |
| -> LoggingT m a |
Within the LoggingT monad, capture all log messages to a bounded
channel of the indicated size, and only actually log them if there is an
exception.
Since: monad-logger-0.3.2
unChanLoggingT :: (MonadLogger m, MonadIO m) => Chan LogLine -> m void #
Read logging tuples from an unbounded channel and log them into a
MonadLoggerIO monad, forever.
For use in a dedicated thread with a channel fed by runChanLoggingT.
Since: monad-logger-0.3.17
runChanLoggingT :: MonadIO m => Chan LogLine -> LoggingT m a -> m a #
Run a block using a MonadLogger instance which writes tuples to an
unbounded channel.
The tuples can be extracted (ie. in another thread) with unChanLoggingT
or a custom extraction funtion, and written to a destination.
Since: monad-logger-0.3.17
execWriterLoggingT :: Functor m => WriterLoggingT m a -> m [LogLine] #
Run a block using a MonadLogger instance. Return logs in a list
| @since 0.3.28
runWriterLoggingT :: Functor m => WriterLoggingT m a -> m (a, [LogLine]) #
Run a block using a MonadLogger instance. Return a value and logs in a list
| @since 0.3.28
Generates a function that takes a LogSource, a level name and a Text and logs a LevelOther message. Usage:
$logOtherS "SomeSource" "My new level" "This is a log message"
Generates a function that takes a LogSource and Text and logs a LevelDebug message. Usage:
$logDebugS "SomeSource" "This is a debug log message"
logOtherSH :: Text -> Q Exp #
Generates a function that takes a 'Show a => a' and logs a LevelOther message. Usage:
$(logOtherSH "My new level") "This is a log message"
logErrorSH :: Q Exp #
See logDebugSH
See logDebugSH
See logDebugSH
logDebugSH :: Q Exp #
Generates a function that takes a 'Show a => a' and logs a LevelDebug message. Usage:
$(logDebugSH) (Just "This is a debug log message")
Since: monad-logger-0.3.18
Constructors
| LevelDebug | |
| LevelInfo | |
| LevelWarn | |
| LevelError | |
| LevelOther Text |
class Monad m => MonadLogger (m :: Type -> Type) where #
A Monad which has the ability to log messages in some manner.
Minimal complete definition
Nothing
Instances
class (MonadLogger m, MonadIO m) => MonadLoggerIO (m :: Type -> Type) where #
An extension of MonadLogger for the common case where the logging action
is a simple IO action. The advantage of using this typeclass is that the
logging function itself can be extracted as a first-class value, which can
make it easier to manipulate monad transformer stacks, as an example.
Since: monad-logger-0.3.10
Minimal complete definition
Nothing
Methods
askLoggerIO :: m (Loc -> LogSource -> LogLevel -> LogStr -> IO ()) #
Request the logging function itself.
Since: monad-logger-0.3.10
Instances
newtype NoLoggingT (m :: Type -> Type) a #
Monad transformer that disables logging.
Since: monad-logger-0.2.4
Constructors
| NoLoggingT | |
Fields
| |
Instances
newtype WriterLoggingT (m :: Type -> Type) a #
Since: monad-logger-0.3.28
Constructors
| WriterLoggingT | |
Fields
| |
Instances
newtype LoggingT (m :: Type -> Type) a #
Monad transformer that adds a new logging function.
Since: monad-logger-0.2.2
Instances
Constructors
| Loc | |
Fields
| |
Instances
| Data Loc | |
Defined in Language.Haskell.TH.Syntax Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Loc -> c Loc # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Loc # dataTypeOf :: Loc -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Loc) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Loc) # gmapT :: (forall b. Data b => b -> b) -> Loc -> Loc # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Loc -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Loc -> r # gmapQ :: (forall d. Data d => d -> u) -> Loc -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Loc -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Loc -> m Loc # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Loc -> m Loc # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Loc -> m Loc # | |
| Generic Loc | |
| Show Loc | |
| Eq Loc | |
| Ord Loc | |
| type Rep Loc | |
Defined in Language.Haskell.TH.Syntax type Rep Loc = D1 ('MetaData "Loc" "Language.Haskell.TH.Syntax" "template-haskell" 'False) (C1 ('MetaCons "Loc" 'PrefixI 'True) ((S1 ('MetaSel ('Just "loc_filename") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 String) :*: S1 ('MetaSel ('Just "loc_package") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 String)) :*: (S1 ('MetaSel ('Just "loc_module") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 String) :*: (S1 ('MetaSel ('Just "loc_start") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 CharPos) :*: S1 ('MetaSel ('Just "loc_end") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 CharPos))))) | |