Skip to content

Instantly share code, notes, and snippets.

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 aitoroses/0fea13d2b870d98a0c77af1bf8301b3d to your computer and use it in GitHub Desktop.
Save aitoroses/0fea13d2b870d98a0c77af1bf8301b3d to your computer and use it in GitHub Desktop.
module Main where
import Prelude
import Control.Monad.Reader (Reader, runReader, ReaderT(..), runReaderT, ask, class MonadAsk)
import Effect (Effect)
import Effect.Class (class MonadEffect, liftEffect)
import Effect.Console (log)
---------------------------------------------------------
-- 01 no Reader
---------------------------------------------------------
data Config = Config String
getConfig :: Config -> String
getConfig (Config c) = c
main01 :: Effect Unit
main01 = do
log $ getConfig config
where config = (Config " ***** foo ***** ")
---------------------------------------------------------
-- 02 with Reader
-- getConfigR doesn't need to be passed config directly
-- as it is within the context of the monad
---------------------------------------------------------
getConfigR :: Reader Config String
getConfigR = do
config <- ask
pure (getConfig config)
main02 :: Effect Unit
main02 = do
log $ runReader getConfigR config
where config = (Config " ***** fooR ***** ")
---------------------------------------------------------
-- 03 with ReaderT
-- Now we can combine a side effect while also asking for the config
---------------------------------------------------------
getConfigRT :: ReaderT Config Effect String
getConfigRT = do
config <- ask
liftEffect (log "side effect!")
pure (getConfig config)
main03 :: Effect Unit
main03 = do
r <- runReaderT getConfigRT config
log r
where config = (Config " ***** fooR ***** ")
---------------------------------------------------------
-- 04 with App as a newType
-- We start creating now a App Monad with the behaviours we want
---------------------------------------------------------
newtype App a = App (ReaderT Config Effect a)
derive newtype instance bindApp ∷ Bind App
derive newtype instance applicativeApp ∷ Applicative App
derive newtype instance monadAskApp :: MonadAsk Config App
derive newtype instance monadEffectApp :: MonadEffect App
getConfigApp :: App String
getConfigApp = do
config <- ask
liftEffect (log "side effect!")
pure (getConfig config)
runApp :: forall a. App a -> Config -> Effect a
runApp (App readerT) c = runReaderT readerT c
main04 :: Effect Unit
main04 = do
r <- runApp getConfigApp config
log r
where config = (Config " ***** fooR ***** ")
---------------------------------------------------------
-- 05 with constrains
-- Now we uncouple the functions from the app by
-- declaring what are the characteristics of the monad
-- where this function is going to execute, instead of the actual monad
-- so that we can add new things without changing the App monad types everywhere
---------------------------------------------------------
newtype AppC a = AppC (ReaderT Config Effect a)
derive newtype instance bindAppC ∷ Bind AppC
derive newtype instance applicativeAppC ∷ Applicative AppC
derive newtype instance monadAskAppC :: MonadAsk Config AppC
derive newtype instance monadEffectAppC :: MonadEffect AppC
getConfigAppC :: forall m. MonadEffect m => MonadAsk Config m => m Unit
getConfigAppC = do
config <- ask
liftEffect (log (getConfig config))
runAppC :: forall a. AppC a -> Config -> Effect a
runAppC (AppC readerT) c = runReaderT readerT c
main05 :: Effect Unit
main05 = do
runAppC getConfigAppC config
where config = (Config " Show me ")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment