Modułowy projekt programu - łączenie transformatorów monadowych w funkcje agnostyczne Monada

Próbuję wymyślić modułowy program, a ja ponownie proszę o pomoc.

W następstwie następujących postówTransformatory monadowe a parametry przejścia iProjekt dużej skali w Haskell, Próbuję zbudować dwa niezależne moduły, które używają transformatorów Monad, ale eksponują funkcje agnostyczne Monada, a następnie łączą funkcję agnostyczną Monad z każdego z tych modułów w nową funkcję agnostyczną Monad.

Nie mogłem uruchomić funkcji łączenia, np. jak zadzwonićmainProgram za pomocąrunReaderT w poniższym przykładzie?

Pytanie uzupełniające brzmi: czy istnieje lepszy sposób na osiągnięcie tego samego celu projektowania modułowego?

Przykład ma dwa makiety modułów (ale kompiluje), jeden wykonujący rejestrację i taki, który odczytuje dane wprowadzone przez użytkownika i manipuluje nim. Funkcja łączenia odczytuje dane wprowadzone przez użytkownika, rejestruje je i drukuje.

{-# LANGUAGE FlexibleContexts #-}

module Stackoverflow2 where

import Control.Monad.Reader

----
---- From Log Module - Writes the passed message in the log
---- 

data LogConfig = LC { logFile :: FilePath }

doLog :: (MonadIO m, MonadReader LogConfig m) => String -> m ()
doLog _ = undefined


----
---- From UserProcessing Module - Reads the user Input and changes it to the configured case
----

data  MessageCase = LowerCase | UpperCase deriving (Show, Read)

getUserInput :: (MonadReader MessageCase m, MonadIO m) => m String
getUserInput = undefined

----
---- Main program that combines the two
----                  

mainProgram :: (MonadReader MessageCase m, MonadReader LogConfig m, MonadIO m) => m ()
mainProgram = do input <- getUserInput
                 doLog input
                 liftIO $ putStrLn $ "Entry logged: " ++ input

questionAnswers(2)

yourAnswerToTheQuestion