Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is "a function that you call" and what is "a function that call you"?

I'm trying to understand what is Haskell Reader monad, but I struggle with this part in the book:

The “read-only” nature of the type argument r means that you can swap in a different type or value of r for functions that you call, but not for functions that call you. The best way to demonstrate this is with the withReaderT function which lets us start a new Reader context with a different argument being provided:

withReaderT 
  :: (r' -> r) 
  -- ^ The function to modify the environment. 
  -> ReaderT r m a 
  -- ^ Computation to run in the modified environment. 
  -> ReaderT r' m a 

So, first of all, could you please specify what to consider "a function that you call" and what to consider "a function that call you"?

like image 455
kirill fedorov Avatar asked Dec 31 '22 00:12

kirill fedorov


1 Answers

I think this is just an English language misunderstanding. When it says "you", it just means "the code you are currently concerned with".

If you are writing a function myfunction:

myfunction x y = sqrt (x*x + y*y)
main = print $ myfunction 3 4

If we say that you are myfunction, then sqrt is a function that you call, and main is a function that calls you.

The point the book is trying to make is that your code can call functions with any environment you want, but those functions can not change the environment for your code. In turn, code that calls your code can specify any environment it wants you to see, but you can not change the environment for that code.

Here's a commented example:

import Control.Monad.IO.Class
import Control.Monad.Trans.Reader
import Control.Monad.Trans

showValue :: String -> ReaderT String IO ()
showValue str = do
    s <- ask
    lift . putStrLn $ str ++ ": " ++ s

-- This is me (i.e. my code). 
-- I show the environment twice, and it's guaranteed to be the same both times
myFunction :: ReaderT String IO ()
myFunction = do
    showValue "myFunction sees"
    withReaderT (const "Something Completely Different") functionThatICall
    showValue "myFunction still sees"

-- This is a function that I call.
-- I decide what value it sees, but it can't decide what I see.
functionThatICall :: ReaderT String IO ()
functionThatICall = showValue "functionThatICall sees"

-- This is a function that calls me. It decides what value I see,
-- but I can't change what it sees.
functionThatCallsMe :: ReaderT String IO ()
functionThatCallsMe = do
    showValue "functionThatCallsMe sees"
    myFunction
    showValue "functionThatCallsMe still sees"


main = runReaderT functionThatCallsMe "Hello World"
like image 178
that other guy Avatar answered Jan 02 '23 14:01

that other guy