什么是“你调用的函数”,什么是“调用你的函数”?

kir*_*rov 4 haskell reader-monad

我试图理解什么是 Haskell Reader monad,但我在书中的这一部分很挣扎:

类型参数的“只读”性质r意味着您可以r为您调用的函数交换不同的类型或值,但不能为调用您的函数交换。证明这一点的最好方法是使用该withReaderT函数,该函数让我们开始一个新的Reader上下文,并提供不同的参数:

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

那么,首先,您能否具体说明什么是“您调用的函数”,什么是“调用您的函数”?

tha*_*guy 9

我认为这只是对英语的误解。当它说“你”时,它只是意味着“你当前关心的代码”。

如果您正在编写函数myfunction

myfunction x y = sqrt (x*x + y*y)
main = print $ myfunction 3 4
Run Code Online (Sandbox Code Playgroud)

如果我们说你是myfunction,那么sqrt就是一个你调用main的函数,并且是一个调用你的函数。

这本书试图说明的一点是,您的代码可以在您想要的任何环境下调用函数,但这些函数不能更改代码的环境。反过来,调用您的代码的代码可以指定它希望您看到的任何环境,但您不能更改该代码的环境。

这是一个注释示例:

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"
Run Code Online (Sandbox Code Playgroud)