 ;;just like the reader monad in haskell
 (def reader-m {:return (fn [a]
                          (fn [_] a))
-               :>>=   (fn [m k]
+               :>>=    (fn [m k]
                          (fn [r]
                            ((k (m r)) r)))})
 

;;但是貌似defprotocol和reify的组合本身就可以这样弄 就是repo那里使用let绑定为mk-user-repo的位置 用reader monad会让代码描述性更强 repo就是单独传入的一个module一样的意思
;;如果不用reader monad那么用mk-user-repo函数生成的repo值还需要显示的被传入clone!函数 现在只要在最外层显式地写一次就好了
;;其实这样看来 上面传递env的那个例子也算是一种依赖注入 依赖就是env这个上下文中保存的信息

        [_ (connect-to-db-m)
         _ (connect-to-api-m)]
        (prn "Done.")))

(defn connect-to-db-m-2 []
  (do-m reader-m
        [db-uri (asks :db-uri)]
        (str "Connected to db at %s" db-uri)))

(defn connect-to-api-m-2 []
  (do-m reader-m
        [api-key (asks :api-key)]
        (str "Connected to api with key %s" api-key)))

(defn run-app-m-2 []
  (do-m reader-m
        [dbinfo (connect-to-db-m-2)
         apiinfo (connect-to-api-m-2)]
        (str "dbinfo -> " dbinfo "apiinfo -> " apiinfo)))

(macroexpand '(do-m reader-m
                    [_ (connect-to-db-m)
