Last active
May 5, 2020 11:58
-
-
Save piotr-yuxuan/c916f4daef652bc8347bba2a703ad4fd to your computer and use it in GitHub Desktop.
Exploration of a few funcool.cats control flow structures
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns meew | |
(:require [cats.core :refer [mlet do-let extract return]] | |
[cats.monad.either :refer [branch-left left right]])) | |
(defn http-get! [{:keys [success-rate some-arg]}] | |
(-> (repeat success-rate {:status :ok, :result (* some-arg (rand-int 10))}) | |
(conj {:status :ko, :error "computation error!"}) | |
rand-nth)) | |
;; ✅ stop at the first error | |
;; ❌ custom error handling | |
;; ❌ return the last successful computation | |
;; ❌ reuse previous computations | |
;; ❌ return a aggregated reduction in case of all successful computation | |
;; ✅ keep reading complexity low | |
(and | |
(= :ok (:status (http-get! {:success-rate 8 :some-arg 1}))) | |
(= :ok (:status (http-get! {:success-rate 4 :some-arg 2}))) | |
(= :ok (:status (http-get! {:success-rate 2 :some-arg 3})))) | |
;; ✅ stop at the first error | |
;; ❌ custom error handling | |
;; ❌ return the last successful computation | |
;; ❌ reuse previous computations | |
;; ❌ return a aggregated reduction in case of all successful computation | |
;; 🟠 keep reading complexity low | |
(condp (fn [{:keys [status]} ko] (println :condp-test :status status) (= status ko)) :ko | |
(http-get! {:success-rate 10 :some-arg 1}) "first computation failed" ;; doesn't depend on the error | |
(http-get! {:success-rate 10 :some-arg 2}) "second computation failed" | |
(http-get! {:success-rate 10 :some-arg 3}) "third computation failed" | |
"all computations succeeded") | |
;; ✅ stop at the first error | |
;; ❌ custom error handling | |
;; ✅ return the last successful computation | |
;; ❌ reuse previous computations | |
;; ❌ return a aggregated reduction in case of all successful computation | |
;; ❌ keep reading complexity low | |
(condp (fn [{:keys [status]} ko] (println :condp-test :status status) (= status ko)) :ko | |
(http-get! {:success-rate 10 :some-arg 1}) "first computation failed" | |
(http-get! {:success-rate 10 :some-arg 2}) "second computation failed" | |
(http-get! {:success-rate 10 :some-arg 3})) | |
;; ✅ stop at the first error | |
;; ✅ custom error handling | |
;; ❌ return the last successful computation | |
;; ❌ reuse previous computations | |
;; ❌ return a aggregated reduction in case of all successful computation | |
;; ❌ keep reading complexity low | |
(condp (fn [{:keys [status] :as response} ko] (when (= status ko) response)) :ko | |
(http-get! {:success-rate 10 :some-arg 1}) | |
:>> (fn [{:keys [error]}] (str "computation 1 failed, error is: " error)) | |
(http-get! {:success-rate 10 :some-arg 2}) | |
:>> (fn [{:keys [error]}] (str "computation 2 failed, error is: " error)) | |
(http-get! {:success-rate 10 :some-arg 3}) | |
:>> (fn [{:keys [error]}] (str "computation 3 failed, error is: " error)) | |
"all computations succeeded, but we can't access results") | |
;; ✅ stop at the first error | |
;; ✅ custom error handling | |
;; ✅ return the last successful computation | |
;; ✅ reuse previous computations | |
;; ✅ return a aggregated reduction in case of all successful computation | |
;; ❌ keep reading complexity low | |
(let [{:keys [status] :as first-computation} (http-get! {:success-rate 10 :some-arg 1})] | |
(if (= :ok status) | |
(let [{:keys [status] :as second-computation} (http-get! {:success-rate 10 :some-arg 2})] | |
(if (= :ok status) | |
(let [{:keys [status] :as third-computation} (http-get! {:success-rate 10 :some-arg 3})] | |
(if (= :ok status) | |
{:transaction-response (reduce + (map :result [first-computation second-computation third-computation]))} | |
third-computation)) | |
second-computation)) | |
first-computation)) | |
(defn http-get-either! [query] | |
(let [{:keys [status] :as response} (http-get! query)] | |
(if (= :ok status) | |
(right response) | |
(left {:status :ko, :error "computation error!"})))) | |
;; ✅ stop at the first error | |
;; ❌ custom error handling | |
;; ✅ return the last successful computation | |
;; ❌ reuse previous computations | |
;; ❌ return a aggregated reduction in case of all successful computation | |
;; ✅ keep reading complexity low | |
(extract | |
(do-let | |
(http-get-either! {:success-rate 10 :some-arg 1}) | |
(http-get-either! {:success-rate 10 :some-arg 2}) | |
(http-get-either! {:success-rate 10 :some-arg 3}))) | |
;; ✅ stop at the first error | |
;; ❌ custom error handling | |
;; ✅ return the last successful computation | |
;; ❌ reuse previous computations | |
;; ❌ return a aggregated reduction in case of all successful computation | |
;; ✅ keep reading complexity low | |
(extract | |
(do-let | |
(http-get-either! {:success-rate 10 :some-arg 1}) | |
(http-get-either! {:success-rate 10 :some-arg 2}) | |
(http-get-either! {:success-rate 10 :some-arg 3}) | |
(right {:message "all computations succeeded, but we can't access results"}))) | |
;; ✅ stop at the first error | |
;; ❌ custom error handling | |
;; ✅ return the last successful computation | |
;; ✅ reuse previous computations | |
;; ✅ return a aggregated reduction in case of all successful computation | |
;; ✅ keep reading complexity low | |
(extract | |
(mlet [first-computation (http-get-either! {:success-rate 8 :some-arg 1}) | |
second-computation (http-get-either! {:success-rate 4 :some-arg 2}) | |
third-computation (http-get-either! {:success-rate 2 :some-arg 3})] | |
(return {:transaction-response (reduce + (map :result [first-computation second-computation third-computation]))}))) | |
;; ✅ stop at the first error | |
;; 🟠 custom error handling | |
;; ✅ return the last successful computation | |
;; ✅ reuse previous computations | |
;; ❌ return a aggregated reduction in case of all successful computation | |
;; ✅ keep reading complexity low | |
(extract | |
(branch-left | |
(do-let | |
(http-get-either! {:success-rate 10 :some-arg 1}) | |
(http-get-either! {:success-rate 10 :some-arg 2}) | |
(http-get-either! {:success-rate 10 :some-arg 3})) | |
(fn [response] | |
(left {:error "some computation failed" | |
:failed response})))) | |
;; ✅ stop at the first error | |
;; ✅ custom error handling | |
;; ✅ return the last successful computation | |
;; ✅ reuse previous computations | |
;; ❌ return a aggregated reduction in case of all successful computation | |
;; ✅ keep reading complexity low | |
(extract | |
(do-let | |
(branch-left (http-get-either! {:success-rate 10 :some-arg 1}) (fn [_response] (left {:error "first computation failed"}))) | |
(branch-left (http-get-either! {:success-rate 10 :some-arg 2}) (fn [_response] (left {:error "second computation failed"}))) | |
(branch-left (http-get-either! {:success-rate 10 :some-arg 3}) (fn [_response] (left {:error "third computation failed"}))))) | |
;; ✅ stop at the first error | |
;; ✅ custom error handling | |
;; ✅ return the last successful computation | |
;; ✅ reuse previous computations | |
;; ✅ return a aggregated reduction in case of all successful computation | |
;; ✅ keep reading complexity low | |
(extract | |
(mlet [first-computation (branch-left (http-get-either! {:success-rate 10 :some-arg 1}) (fn [_response] (left {:error "first computation failed"}))) | |
second-computation (branch-left (http-get-either! {:success-rate 10 :some-arg 2}) (fn [_response] (left {:error "second computation failed"}))) | |
third-computation (branch-left (http-get-either! {:success-rate 10 :some-arg 3}) (fn [_response] (left {:error "third computation failed"})))] | |
(return {:transaction-response (reduce + (map :result [first-computation second-computation third-computation]))}))) | |
;; see real-life examples |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment