diff options
author | Paul Oliver <contact@pauloliver.dev> | 2025-09-12 01:43:15 +0000 |
---|---|---|
committer | Paul Oliver <contact@pauloliver.dev> | 2025-09-12 01:43:15 +0000 |
commit | e36a24df176cdbbd634738115f847e4fa46a0aea (patch) | |
tree | 0e76c7651a0b3ec4d190bdf4afd4614630717733 /hsm-log/Hsm/Log.hs | |
parent | ac5a85abac1a47645713d3b7539fccb1b744dd85 (diff) |
Adds `Logs` constraint combinator
Diffstat (limited to 'hsm-log/Hsm/Log.hs')
-rw-r--r-- | hsm-log/Hsm/Log.hs | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/hsm-log/Hsm/Log.hs b/hsm-log/Hsm/Log.hs index 99e5b7c..bd8c73f 100644 --- a/hsm-log/Hsm/Log.hs +++ b/hsm-log/Hsm/Log.hs @@ -5,10 +5,11 @@ module Hsm.Log ( Severity (Attention, Info, Trace) , Log + , Logs + , LogOptionPrefix , getLevel , logMsg , makeLoggerIO - , LoggerOptionPrefix , runLog , runLogOpt , runLogs @@ -18,6 +19,7 @@ where import Control.Monad (when) import Data.Function (applyWhen) +import Data.Kind (Constraint) import Data.List (intercalate) import Data.Proxy (Proxy (Proxy)) import Data.Time.Clock (getCurrentTime) @@ -55,6 +57,18 @@ type instance DispatchOf (Log d) = Static WithSideEffects newtype instance StaticRep (Log d) = Log Severity +-- Constraint combinator for multiple logger effects +-- Simplifies effect constraints for functions requiring multiple loggers. +-- +-- Example: +-- >>> :kind! Logs '["log1", "log2"] es +-- (Log "log1" :> es, Log "log2" :> es) +type family Logs ls es :: Constraint where + Logs '[] es = () + Logs (l : ls) es = (Log l :> es, Logs ls es) + +type LogOptionPrefix = "logLevel_" + getLevel :: Log d :> es => Eff es Severity getLevel = getStaticRep >>= \(Log level) -> return level @@ -83,8 +97,6 @@ makeLoggerIO => Eff es (Severity -> String -> IO ()) makeLoggerIO = unsafeEff $ \env -> return $ \severity message -> unEff (logMsg severity message) env -type LoggerOptionPrefix = "logLevel_" - runLog :: forall d es a . IOE :> es @@ -95,25 +107,25 @@ runLog = evalStaticRep . Log runLogOpt :: forall d f o es a - . (AppendSymbol LoggerOptionPrefix d ~ f, HasField f o Severity, IOE :> es) + . (AppendSymbol LogOptionPrefix d ~ f, HasField f o Severity, IOE :> es) => o -> Eff (Log d : es) a -> Eff es a runLogOpt = runLog . getField @f -class Logs (o :: *) (ds :: [Symbol]) (es :: [Effect]) where +class LogsClass (o :: *) (ds :: [Symbol]) (es :: [Effect]) where type Insert ds es :: [Effect] runLogs :: Severity -> Eff (Insert ds es) a -> Eff es a runLogsOpt :: o -> Eff (Insert ds es) a -> Eff es a -instance Logs (o :: *) ('[] :: [Symbol]) (es :: [Effect]) where +instance LogsClass (o :: *) ('[] :: [Symbol]) (es :: [Effect]) where type Insert '[] es = es runLogs = const id runLogsOpt = const id instance - (AppendSymbol LoggerOptionPrefix d ~ f, HasField f o Severity, IOE :> Insert ds es, KnownSymbol d, Logs o ds es) - => Logs (o :: *) (d : ds :: [Symbol]) (es :: [Effect]) + (AppendSymbol LogOptionPrefix d ~ f, HasField f o Severity, IOE :> Insert ds es, KnownSymbol d, LogsClass o ds es) + => LogsClass (o :: *) (d : ds :: [Symbol]) (es :: [Effect]) where type Insert (d : ds) es = Log d : Insert ds es runLogs level = runLogs @o @ds level . runLog @d level |