module Log = let info (env: #ILog) = env.Logger.Info("Message")
module Db = let fetchUser (env: #IDb) = env.Database.Query(...)
+
+
优点:
+
+
显式依赖声明:函数签名仅需env参数,编译器验证接口实现。
+
模块化隔离:各模块仅声明所需接口(如ILog、IDb),避免全局依赖。
+
易于测试:通过模拟env实现单元测试,无需依赖具体实现。
+
+
应用场景:
+
let changePass env req =task { let! user = Db.fetchUser env req.UserId Log.info env "Processing user: %i" user.Id ... }
+
+
+
三、Reader Monad
为消除显式的env传递,可引入 Reader Monad,将环境隐式注入计算流程:
+
[<Struct>]typeEffect<'env, 'out>= Effect of ('env->'out)
module Effect = let run env (Effect fn) = fn env let bind f effect = Effect (fun env -> run env (f (run env effect)))
typeEffectBuilder() = member __.Bind(e, f) = Effect.bind f e member __.Return(x) = Effect (fun _ -> x)
let effect = EffectBuilder()
+
+
然后:
+
let changePass req =effect { let! user = Db.fetchUser req.UserId let! salt = Random.bytes 32 do! Log.info "Password updated for user %i" user.Id returnOk() }