Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9013631
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T03:18:59+00:00 2026-06-16T03:18:59+00:00

module Main (main) where import Control.Monad.Reader p1 :: String -> IO () p1 =

  • 0
module Main (main) where

import Control.Monad.Reader

p1 :: String -> IO ()
p1 = putStrLn . ("Apple "++)

p2 :: String -> IO ()
p2 = putStrLn . ("Pear "++)

main :: IO ()
main = do
    p1 "x"
    p2 "y"
    r "z"

r :: String -> IO ()
r = do
    p1
    p2

It prints:

Apple x
Pear y
Pear z

Why?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-16T03:19:00+00:00Added an answer on June 16, 2026 at 3:19 am

    The problem is in r. Given the following definition of Reader monad:

    instance Monad ((->) e) where
        return = const
        f >>= g = \x -> g (f x) x
    

    We can simplify r:

    r = p1 >> p2    
      = (>>=) p1 (\_ -> p2)    
      = (\f g x -> g (f x) x) p1 (\_ -> p2)    
      = \x -> (\_ -> p2) (p1 x) x    
      = \x -> p2 x
    

    This also shows that Reader‘s (>>) is just const with a bit more specific type.

    If you want to distribute the environment and then execute both actions, you have to bind the result of applying p1 to the environment, for example:

    r = do a1 <- p1
           a2 <- p2
           return (a1 >> a2)
    

    Or using Applicative:

    r = (>>) <$> p1 <*> p2
    

    Expanding on the Reader part, Control.Monad.Reader provides three variants of Reader.

    • the implicit (->) e, which is what the function r uses
    • the monad transformer ReaderT e m, a newtype wrapper for functions of type e -> m a
    • the explicit Reader e, defined in terms of ReaderT as ReaderT e Identity

    Without any further information, the implicit (->) e will be used. Why?

    The overall type of do block is given by the last expression, which is also constrained to be of the form Monad m => m a for some m and a.

    Looking back at r, it’s clear that the do block has a type String -> IO () as given by the type of r and also p2. It also requires String -> IO () to be Monad m => m a. Now, unifying these two types:

    m = (->) String
    a = IO ()
    

    This matches (->) e monad instance by choosing e = String.


    Being a monad transformer, ReaderT takes care of the inner plumbing to make sure the actions of the inner monad are properly sequenced and executed. To select ReaderT, it is necessary to explicitly mention it (usually in a type signature, but functions which fix the type to be ReaderT, such as runReaderT, also work):

    r :: ReaderT String IO ()
    r = do ? p1
           ? p2
    
    r' :: String -> IO ()
    r' = runReaderT r
    

    This comes with another problem, p1 and p2 have a type String -> IO (), which doesn’t match the required ReaderT String IO ().

    The ad-hoc solution (tailored exactly for this situation), is just to apply

    ReaderT :: (e -> m a) -> ReaderT e m a
    

    To obtain something more general, MonadIO type class can lift IO actions into the transformer and MonadReader type class allows accessing the environment. These two type classes work as long as there is IO (or ReaderT respectively) somewhere in the transformer stack.

    lift' :: (MonadIO m, MonadReader a m) => (a -> IO b) -> m b
    lift' f = do
        env <- ask     -- get environment
        let io = f env -- apply f to get the IO action
        liftIO io      -- lift IO action into transformer stack
    

    Or more concisely:

    lift' f = ask >>= liftIO . f
    

    Regarding your question in comments, you can implement the relevant instances in this way:

    newtype ReaderT e m a = ReaderT { runReaderT :: e -> m a }
    
    instance Monad m => Monad (ReaderT e m) where
        return  = ReaderT . const . return
          -- The transformers package defines it as "lift . return".
          -- These two definitions are equivalent, though.
        m >>= f = ReaderT $ \e -> do
            a <- runReaderT m e
            runReaderT (f a) e
    
    instance Monad m => MonadReader e (ReaderT e m) where
        ask        = ReaderT return
        local  f m = ReaderT $ runReaderT m . f
        reader f   = ReaderT (return . f)
    

    The actual typeclass can be found in the mtl package (package, type class), the newtype and Monad instance in transformers package (package, type class).


    As for making a e -> m a Monad instance, you are out of luck. Monad requires a type constructor of kind * -> *, which means we are attempting to do something like this (in pseudo-code):

    instance Monad m => Monad (/\a -> e -> m a) where
        -- ...
    

    where /\ stands for type-level lambda. However, the closest thing we can get to a type level lambda is a type synonym (which must be fully applied before we can make type class instances, so no luck here) or a type family (which cannot be used as an argument to type class either). Using something like (->) e . m leads to newtype again.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have the following program: module Main where import System (getArgs) import Control.Concurrent import
capslocker.hs has following code: import Control.Monad import Data.Char main = forever $ do putStr
What is wrong here, is Lazy Evaluation too? teste.hs module Main where import Control.Parallel(par,pseq)
Three module exists. Cfg, Main and Component Cfg.py value = 0 Component.py import Cfg
When I try to compile this: module Main where import qualified Data.Vector.Unboxed.Mutable as MV
Here is a snippet of my code: import Control.Monad.State as S get x =
I'm a haskell beginner. My code: module Main (main) where import System.IO --Type for
This question is certainly for stackoverflow.com here is the sample module Main where import
When I try to run this code... module Main where import qualified Data.Text.Lazy.IO as
The following program does not work as expected: module Main where import Graphics.UI.Gtk import

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.