main :: IO ()
main = do
putStrLn "Hello, what is your name?"
name <- readLine
putStrLn ("Hello " <> name <> "!")IO, State, Reader, Writer, Except, [], Maybe, …
You are free to create your own as long as you obey monad laws.
Monads do not compose well
State s a → Monad m => StateT s m a
newtype ProtocolT m a = ProtocolT (ReaderT Request (WriterT Response (MaybeT m)) a)
deriving (Applicative, Functor, Monad):-(
type Protocol = '[Reader Request, Writer Response, Exc ()]
action :: Members Protocol effs => Eff effs a
-- action :: Monad m => ProtocolT m aApproach to computational effects based on a premise that impure behaviour arises from a set of operations
Eff)action uses only those effects it requires, but stack can contain any, even our custom ones.data Console s where
PutStrLn :: String -> Console ()
GetLine :: Console String
putStrLn' :: Member Console r => String -> Eff r ()
putStrLn' = send . PutStrLn
getLine' :: Member Console r => Eff r String
getLine' = send GetLinehello :: Member Console effs => Eff effs ()
hello = do
putStrLn' "Hello, what is your name?"
name <- readLine'
putStrLn' ("Hello " <> name <> "!")runConsoleIO :: Member IO r => Eff (Console ': r) w -> Eff r wmain :: IO ()
main = runM (runConsoleIO hello)
-- | | |
-- IO () -' | |
-- Eff '[IO] () -' |
-- Eff '[Console, IO] () -'runConsolePure :: [String] -> Eff (Console ': r) a
-> Eff r (a, ([String], [String]))
-- ^ (value, (unconsumed input, produced output)):-)lift, …)exampleEcho :: Member Console r => Eff r ()
exampleEcho = forever $ do
putStrLn' "Send me something to echo..."
s <- getLine'
putStrLn' ("Thanks for sending " ++ show s)
mainEcho :: IO ()
mainEcho = runM (runConsoleM exampleEcho)
-- | | |
-- IO () -' | |
-- Eff '[IO] () -' |
-- Eff '[Console, IO] () -'data Capitalize v where
Capitalize :: String -> Capitalize String
capitalize :: Member Capitalize r => String -> Eff r String
capitalize = send . Capitalize
runCapitalizeM :: Eff (Capitalize ': r) w -> Eff r wexampleCapitalize :: Members '[Console, Capitalize] effs => Eff effs ()
exampleCapitalize = forever $ do
putStrLn' "Send me something to capitalize..."
l <- getLine'
when (null l) exitSuccess'
capitalize l >>= putStrLn'mainCapitalize1 :: IO ()
mainCapitalize1 = runM (runConsoleM (runCapitalizeM exampleCapitalize))
-- | | | |
-- IO () -' | | |
-- Eff '[IO] () -' | |
-- Eff '[Console, IO] () -' |
-- Eff '[Capitalize, Console, IO] () -'mainCapitalize2 :: IO ()
mainCapitalize2 = runM (runCapitalizeM (runConsoleM exampleCapitalize))
-- | | | |
-- IO () -' | | |
-- Eff '[IO] () -' | |
-- Eff '[Capitalize, IO] () -' |
-- Eff '[Console, Capitalize, IO] () -'Functor, Applicative, MonadReaderWriterStateExceptionNonDetCoroutineFreshTraceCut