Last active
April 2, 2023 12:07
-
-
Save eckyputrady/4cfa4eb0eb8370cb50c7ffaa92d33e2c to your computer and use it in GitHub Desktop.
Haskell Clean Architecture
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
----------------------------- | |
-- Domain.hs | |
type SessionId = Text | |
type UserId = Text | |
type User = Text | |
class (Monad m) => UserRepo m where | |
getUserById :: UserId -> m User | |
class (Monad m) => SessionRepo m where | |
getUserIdBySession :: SessionId -> m UserId | |
getUser :: (UserRepo m, SessionRepo m) | |
=> SessionId -> m User | |
getUser sId = getUserIdBySession sId | |
>>= getUserById | |
----------------------------- | |
-- Routes.hs | |
import qualified Domain | |
routes :: (Domain.UserRepo m, Domain.SessionRepo m) => m () | |
routes = | |
get "/user" $ do | |
sId <- parseSessionFromCookiesSomehow | |
user <- Domain.getUser sId | |
displayUserSomeHow user | |
----------------------------- | |
-- Redis.hs | |
import qualified Domain | |
acquireConnection :: IO Connection | |
acquireConnection = ... | |
getUserById :: (Reader Connection m) | |
=> Domain.UserId -> m Domain.User | |
getUserById = ... | |
getUserIdBySession :: (Reader Connection m) | |
=> Domain.Session -> m Domain.UserId | |
getUserIdBySession = ... | |
----------------------------- | |
-- Main.hs | |
import qualified Domain | |
import qualified Redis | |
import qualified Routes | |
newtype App a = App | |
{ unApp :: ReaderT Connection IO a | |
} deriving ( Applicative, Functor, Monad | |
, MonadReader Connection, MonadIO | |
) | |
instance Domain.UserRepo App where | |
getUserById = Redis.getUserById | |
instance Domain.SessionRepo App where | |
getUserIdBySession = Redis.getUserIdBySession | |
main = do | |
conn <- Redis.acquireConnection | |
flip runReaderT conn . unApp $ Routes.routes |
@arnemileswinter You might be interested in https://github.com/eckyputrady/haskell-scotty-realworld-example-app that uses the similar structure as this gist
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wonderful example! Just like @reouno said, a compiling instance would be nice.