读者莫纳德 - 琐碎案例的解释

mat*_*ias 1 haskell reader-monad

我一直试图掌握读者monad并且遇到了这个教程.在其中,作者提出了这个例子:

example2 :: String -> String
example2 context = runReader (greet "James" >>= end) context
    where
        greet :: String -> Reader String String
        greet name = do
            greeting <- ask
            return $ greeting ++ ", " ++ name

        end :: String -> Reader String String
        end input = do
            isHello <- asks (== "Hello")
            return $ input ++ if isHello then "!" else "."
Run Code Online (Sandbox Code Playgroud)

我知道这是一个显示机制的简单例子,但我想弄清楚为什么它比做类似的东西更好:

example3 :: String -> String
example3 = end <*> (greet "James")
  where
    greet name input = input ++ ", " ++ name
    end   input      = if input == "Hello" then (++ "!") else (++ ".")
Run Code Online (Sandbox Code Playgroud)

use*_*560 7

Reader在实际代码中通常不会单独使用它.正如您所观察到的,这并不仅仅是将额外的参数传递给您的函数.但是,作为monad变换器的一部分,它是通过应用程序传递配置参数的绝佳方法.通常,这是通过向MonadReader需要访问配置的任何函数添加约束来完成的.

这是一个更现实世界的例子:

data Config = Config
  { databaseConnection :: Connection
  , ... other configuration stuff
  }

getUser :: (MonadReader Config m, MonadIO m) => UserKey -> m User
getUser x = do
   db <- asks databaseConnection
   .... fetch user from database using the connection
Run Code Online (Sandbox Code Playgroud)

然后你main会看起来像:

main :: IO ()
main = do
  config <- .... create the configuration
  user <- runReaderT (getUser (UserKey 42)) config
  print user
Run Code Online (Sandbox Code Playgroud)