Skip to content

Instantly share code, notes, and snippets.

@mcksp

mcksp/threehs.md Secret

Created April 19, 2024 14:29
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 mcksp/dd26688ba141c9d2a1771f8803952ad3 to your computer and use it in GitHub Desktop.
Save mcksp/dd26688ba141c9d2a1771f8803952ad3 to your computer and use it in GitHub Desktop.

Hi, I try to understand three layer haskell https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html Lets say I have right now I have code

data Env = Env { db :: SQL.Connection }
newType App a = App { runApp :: ReaderT Env IO a }

getUser :: Text -> App (Maybe User)
getUser id = do
    conn <- asks db
    liftIO $ query conn "select..." id

someWebServer $ do
    get "/user" $ do
        user <- getUser "abc"
        render template user

Now, when I try to folow https://github.com/Holmusk/three-layer/tree/master repo that is mentioned as example in this article, the code would look like this:

data Env = Env { db :: SQL.Connection }
newType App a = App { runApp :: ReaderT Env IO a }

class Monad m => AcquireUser m where
    getUser :: Text -> m (Maybe User)

class HasDB env where
    getDB :: env -> Connection

instance HasDB Env where
    getDB = db

grabDB :: (MonadReader env m, HasDB env) => m Connection
grabDB = asks getDB

type WithDb env m = (MonadReader env m, HasDB env, MonadIO m)

instance AcquireUser App where
    getUser = getUserImpl

getUserImpl :: (WithDb env m) => Text -> m (Maybe User)
getUserImpl id = do
    conn <- grabDB
    liftIO $ query conn "select..." id

someWebServer $ do
    get "/user" $ do
        user <- getUser "abc"
        render template user
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment