Haskell-如何将具有不同依赖子集的组件连接在一起?

Haskell-如何将具有不同依赖子集的组件连接在一起?,haskell,dependency-injection,Haskell,Dependency Injection,如何从需要各种基础设施功能子集的组件集成应用程序 有些非常简单,只需要一个配置读取器(我只想为每个业务功能公开一个相关的子集)和一个记录器。有些还需要连接到外部服务(使用缓存),我还想在其中公开与外部世界的有限范围的可能交互 我不想把多个参数显式地传递给这样的函数,也不想把它们包装在一些能够做任何事情的MonadIO中 在Java应用程序容器中注入多个依赖项最接近的方法是什么?该库有类型类来表示从环境中读取配置的计算,monawarder,并将数据写入类似于记录器的东西,MonadWriter。

如何从需要各种基础设施功能子集的组件集成应用程序

有些非常简单,只需要一个配置读取器(我只想为每个业务功能公开一个相关的子集)和一个记录器。有些还需要连接到外部服务(使用缓存),我还想在其中公开与外部世界的有限范围的可能交互

我不想把多个参数显式地传递给这样的函数,也不想把它们包装在一些能够做任何事情的
MonadIO中

在Java应用程序容器中注入多个依赖项最接近的方法是什么?

该库有类型类来表示从环境中读取配置的计算,
monawarder
,并将数据写入类似于记录器的东西,
MonadWriter
。我们将使用这些作为示例

我们将使用的
monawarder
部分是

class Monad m => MonadReader r m | m -> r where
    ask :: m r
我们将使用的
MonadWriter
部分是

class (Monoid w, Monad m) => MonadWriter w m | m -> w where Source  
    tell :: w -> m ()
要要求“多个依赖项”,我们需要一个为多个类型类提供实例的
m

样板 最后,我们将使用中的
ReaderT
WriterT
Identity
来运行我们的示例

{-# LANGUAGE FlexibleContexts #-}

--mtl
import Control.Monad.Reader.Class
import Control.Monad.Writer.Class

--transformers
import Control.Monad.Trans.Reader hiding (ask)
import Control.Monad.Trans.Writer.Strict hiding (tell)
import Data.Functor.Identity
使用多个依赖项:读取配置和日志 我们的读者将从以下环境中阅读:;它将提供一个
monawarder配置

data Configuration = Config { site :: String }
    deriving Show
我们的记录器将累积一个消息列表,每个消息都是一个字符串。它将提供一个
MonadWriter[String]

您可以通过要求多个类型类的实例来要求多个功能。要做到这一点,您可以需要一个
m
,它同时具有
MonadWriter
MonadWriter
的实例。这是一个组件,它需要一个从中读取配置的环境和一种写入日志消息的方法

logConfig :: (MonadWriter String m, MonadReader Configuration m) => m ()
logConfig = do 
    config <- ask
    tell [show config]
举例 我们将在另一个更大的示例中使用前面的
logConfig

example :: (MonadWriter [String] m, MonadReader Configuration m) => m ()
example = do
    tell ["Starting", "Logging Config"]
    logConfig
    tell ["Done Logging Config", "Done"]
最后,我们将使用
配置运行
示例
,并查看它的功能。请注意,此处的
IO
仅用于输出用于运行示例的最终结果

main :: IO ()
main = print . runDepsIdentity example $ Config {site = "StackOverflow"}
这将产生以下输出

((),["Starting","Logging Config","Config {site = \"StackOverflow\"}","Done Logging Config","Done"])
((),["Starting","Logging Config","Config {site = \"StackOverflow\"}","Done Logging Config","Done"])