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 |
Great example. Just like the @aronluigi said, it would be nice if you could expand on it!
Very nice example. Just like the @Woody88 said, it would be nice if you can make runnable code sample.
Wonderful example! Just like @reouno said, a compiling instance would be nice.
@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
Nice example! It will be really nice if you can make the code compile.