Skip to content

Instantly share code, notes, and snippets.

@nikita-volkov
Last active February 5, 2023 19:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikita-volkov/4185a1cdecb3c7e5f008fecad4abef87 to your computer and use it in GitHub Desktop.
Save nikita-volkov/4185a1cdecb3c7e5f008fecad4abef87 to your computer and use it in GitHub Desktop.
ReaderT, ExceptT, IO, composition
-- |
-- Application-wide service, which is merely a product of other services.
-- Shows how services can be de/composed and encapsulated.
module Services.Main where
import qualified Services.Db as Db
import qualified Services.Metrics as Metrics
data Env = Env {
db :: Db.Env,
metrics :: Metrics.Err
}
data Err =
DbErr Db.Err |
MetricsErr Metrics.Err
type Fx = ReaderT Env (ExceptT Err IO)
selectUserEmailById :: Int -> Fx (Maybe Text)
selectUserEmailById id = do
result <- runDbFx $ Db.selectUserEmailById id
runMetricsFx $ Metrics.bump "selectUserEmailById"
return result
runDbFx :: Db.Fx a -> Fx a
runDbFx =
withReaderT (.db) . mapReaderT (withExceptT DbErr)
runMetricsFx :: Metrics.Fx a -> Fx a
runMetricsFx =
withReaderT (.metrics) . mapReaderT (withExceptT MetricsErr)
-- | Your application database.
module Services.Db where
-- | Database-specific environment (usually a connection, or a pool of connections).
data Env
-- | Database-specific error.
data Err
type Fx = ReaderT Env (ExceptT Err IO)
selectUserEmailById :: Int -> Fx (Maybe Text)
-- | Client to some metrics service.
module Services.Metrics where
-- | Your grafana connection or something like that.
data Env
-- | Failure of your metrics service.
data Err
type Fx = ReaderT Env (ExceptT Err IO)
-- | Increment metric by name.
bump :: Text -> Fx ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment