Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Haskell Clean Architecture
-----------------------------
-- 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
@aronluigi

This comment has been minimized.

Copy link

@aronluigi aronluigi commented Feb 16, 2018

Nice example! It will be really nice if you can make the code compile.

@Woody88

This comment has been minimized.

Copy link

@Woody88 Woody88 commented Mar 11, 2019

Great example. Just like the @aronluigi said, it would be nice if you could expand on it!

@reouno

This comment has been minimized.

Copy link

@reouno reouno commented Sep 16, 2019

Very nice example. Just like the @Woody88 said, it would be nice if you can make runnable code sample.

@arnemileswinter

This comment has been minimized.

Copy link

@arnemileswinter arnemileswinter commented Aug 12, 2021

Wonderful example! Just like @reouno said, a compiling instance would be nice.

@eckyputrady

This comment has been minimized.

Copy link
Owner Author

@eckyputrady eckyputrady commented Aug 12, 2021

@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