我正在关注本教程https://blog.ssanj.net/posts/2014-09-23-A-Simple-Reader-Monad-Example.html
它的树功能让我很尴尬
tom :: Reader String String
tom = do
env <- ask
return (env ++ " This is tom.")
jerry :: Reader String String
jerry = do
env <- ask
return (env ++ " This is Jerry.")
tomAndJerry :: Reader String String
tomAndJerry = do
t <- tom
j <- jerry
return (t ++ "\n" ++ j)
runJerryRun :: String
runJerryRun = (runReader tomAndJerry) "Who is this?"
Run Code Online (Sandbox Code Playgroud)
这些函数不接收任何参数,但它们仍然访问 reader monad,这里发生了什么魔法?这背后的直觉是什么?
我的读者monad是一种全局的?
前两个函数均返回其自己的 Reader monad 实例。然后,您可以将它们组合在一起(在第三个函数中)。
为了论证,让我们替换Reader为IO并做类似的事情,这些函数都不接收任何参数:
getIntFromFile :: IO Int
getIntFromFile = do
x <- readFile "myfile.txt"
pure $ read x :: Int
getIntFromStdin :: IO Int
getIntFromStdin = do
x <- getLine
pure $ read x :: Int
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,两者都使用IOmonad,但它们没有任何共同点。但是,由于它们都使用IOmonad,因此您可以(这就是它的优点)将它们组合在一起,如下所示:
-- | the equivalent of your `tomAndJerry` function
main :: IO ()
main = do
x <- getIntFromFile
y <- getIntFromStdin
print $ x + y
Run Code Online (Sandbox Code Playgroud)
这与教程中的示例的逻辑完全相同,除了使用Reader代替IO。