Recently I had a let in which it would be convenient if the whole expression would short-circuit if one of the bindings would be nil.
This is what the Maybe monad can be used for and funcool cats offers this in the form of mlet, so I could have used that (but I didn’t).

(def sum1
(m/mlet
[a (maybe/just 1)
b (maybe/just 2)]
(m/return (+ a b)))) ;;=> #<Just 3>
(def sum2
(m/mlet
[a (maybe/just 1)
b nil]
(m/return (+ a b)))) ;;=> nil
(def sum3
(m/mlet
[a (maybe/just 1)
b (maybe/nothing)]
(m/return (+ a b)))) ;;=> #<Nothing>
(map maybe/from-maybe [sum1 sum2 sum3]) ;;=> (3 nil nil)

So even in small contexts this library can be useful without imposing category theory on colleagues in the rest of the codebase…
Of course you can also use some-> for this, but this doesn’t let you name bindings.

I wonder if anyone has used funcool cats in real world projects and got any leverage out of it?

I’m reminded of my favorite email thread on algebraic structures in software. I bet there is tons of useful stuff in the cats library, but wow is it hard to figure out what’s going on there. A useful exercise would be a fork of cats that is not permitted to use any terms from abstract algebra. I’ve read the documentation to mlet five times through and I’m still not sure what the hell it does.

mlet is syntactic sugar (macro) just like let can be considered syntactic sugar:

(let [a 1
b 2]
(+ a b))
;; vs
((fn [a]
((fn [b]
(+ a b)) 2)) 1)

Without the mlet syntactic sugar, working with m______ values (e.g. maybe) becomes a bit tedious. Imagine if we could only write the nested functions instead of let.

I’ve personally used funcool/cats quite extensively in my last project. Together with funcool/urania, we had all Urania muses return Maybes (and later on Eithers), and we wrote a little wrapper for Urania operations effectively lifting them to work with monads (we did couple them a bit too much to Maybe semantics at the beginning, which made switching to Either a bit more work, we could’ve done better from the get go with a bit more foresight).

Thanks to it, fetching data from multiple sources, combining and re-combining the results and fetching some more, was down to building a Urania tree with a very monadic flavor.