gpt4 book ai didi

haskell - Haskell 中的依赖注入(inject) : solving the task idiomatically

转载 作者:行者123 更新时间:2023-12-03 05:55:50 32 4
gpt4 key购买 nike

用于依赖注入(inject)的惯用 Haskell 解决方案是什么?

例如,假设您有一个接口(interface) frobby ,并且您需要传递符合 frobby 的实例周围(这些实例可能有多种,例如 foobar )。

典型操作是:

  • 具有某些值的函数 X并返回一些值Y 。例如,这可能是一个数据库访问器,接受 SQL 查询和连接器并返回数据集。您可能需要实现 postgres、mysql 和模拟测试系统。

  • 具有某些值的函数Z并返回与 Z 相关的闭包,专门针对给定的foobar样式,在运行时选择。

一个人解决了这个问题,如下:

http://mikehadlow.blogspot.com/2011/05/dependency-injection-haskell-style.html

但我不知道这是否是管理此任务的规范方法。

最佳答案

我认为正确的答案是,我可能会因为这样说而收到一些反对票:忘记术语依赖注入(inject)。把它忘了吧。这是面向对象世界的流行语,但仅此而已。

让我们解决真正的问题。请记住,您正在解决一个问题,而该问题就是手头的特定编程任务。不要让你的问题成为“实现依赖注入(inject)”。

我们将以记录器为例,因为这是许多程序都希望拥有的基本功能,并且有许多不同类型的记录器:一种记录到 stderr,一种记录到文件,一个数据库,一个什么也不做的数据库。要统一所有它们,您需要一个类型:

type Logger m = String -> m ()

您还可以选择更高级的类型来节省一些击键:

class PrettyPrint a where
pretty :: a -> String

type Logger m = forall a. (PrettyPrint a) => a -> m ()

现在让我们使用后一种变体定义一些记录器:

noLogger :: (Monad m) => Logger m
noLogger _ = return ()

stderrLogger :: (MonadIO m) => Logger m
stderrLogger x = liftIO . hPutStrLn stderr $ pretty x

fileLogger :: (MonadIO m) => FilePath -> Logger m
fileLogger logF x =
liftIO . withFile logF AppendMode $ \h ->
hPutStrLn h (pretty x)

acidLogger :: (MonadIO m) => AcidState MyDB -> Logger m
acidLogger db x = update' db . AddLogLine $ pretty x

您可以看到这是如何构建依赖关系图的。 acidLogger 依赖于 MyDB 数据库布局的数据库连接。将参数传递给函数是表达程序中依赖关系的最自然的方式。毕竟,函数只是一个依赖于另一个值的值。对于行动来说也是如此。如果您的操作取决于记录器,那么它自然是记录器的函数:

printFile :: (MonadIO m) => Logger m -> FilePath -> m ()
printFile log fp = do
log ("Printing file: " ++ fp)
liftIO (readFile fp >>= putStr)
log "Done printing."

看看这有多容易吗?在某些时候,这会让你意识到,当你忘记了面向对象教给你的所有废话时,你的生活会变得多么轻松。

关于haskell - Haskell 中的依赖注入(inject) : solving the task idiomatically,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14327327/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com