加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

设计 – Haskell中的依赖注入:习惯性地解决任务

发布时间:2020-12-14 01:09:46 所属栏目:百科 来源:网络整理
导读:依赖注入的习惯Haskell解决方案是什么? 例如,假设你有一个接口f??robby,你需要传递一个符合frobby的实例(可能有这些实例的多个变种,说,foo和bar)。 典型操作是: 取一些值X并返回一些值Y的函数。例如,这可能是一个数据库访问器,采用SQL查询连接器并返
依赖注入的习惯Haskell解决方案是什么?

例如,假设你有一个接口f??robby,你需要传递一个符合frobby的实例(可能有这些实例的多个变种,说,foo和bar)。

典型操作是:

>取一些值X并返回一些值Y的函数。例如,这可能是一个数据库访问器,采用SQL查询&连接器并返回数据集。你可能需要实现postgres,mysql和一个模拟测试系统。
>获取一些值Z并返回与Z相关的闭包的函数,专用于在运行时选择的给定foo或bar样式。

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

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

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

我认为这里的正确答案是,我可能会收到几个downvote只是这样说:忘记术语依赖注入。把它忘了吧。这是一个来自OO世界的时尚流行词,但没有更多。

让我们来解决真正的问题。请记住,你正在解决一个问题,这个问题是手头的特定编程任务。不要让你的问题“实现依赖注入”。

我们将以一个记录器为例,因为这是许多程序想要拥有的基本功能,并且有很多不同类型的记录器:一个记录到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."

看看这是多么容易?在某些时候,这让你意识到你的生活会多么容易,当你只是忘记了OO已经教给你的所有废话。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读