(defn read-and-add!
[prev]
(print "Enter a number: ")
(+ prev (do (flush)
(Integer/parseInt (read-line)))))
(defn bind
[m next-fn]
(try
(next-fn m)
(catch Exception e (reduced (str e)))))
(defn chain
[init & effects]
(reduce bind init effects))
(println (chain 0
read-and-add!
read-and-add!
read-and-add!))
@lispyclouds for those of us not fluent in monads, can you explain what it's doing? Something to do with state. Or arity?
@worldsendless essentially a Monad is a fancy word to encapsulate uncertainty so that the rest of the code is simpler and composable. Most other languages do it with static types but in clojure it can be done via reduced. If you have a chain of things that can either return a value or reduced, it can be shorted when something bad happens. Like here an exception is thrown and it shorts the rest of the chain.
@lispyclouds sounds like this whole thing needs discussion of threading macros like ->
@worldsendless yep, if you can "teach" -> to be aware of reduced, you dont need the chain. like some-> is aware of nil. that too "technically" is a monad.
@worldsendless im using reduced here to convey a bit more info than just a nil.
@lispyclouds Very cool! Is that nil-extra concept something from Monads?
@lispyclouds ah! So monad we could say that the monad concept is really about containers so that we have uniform "blocks" for everything, including errors?
@lispyclouds Thank you! I have learned.
@worldsendless exactly. monads are simply a design pattern to decouple the machinery so that both predictable code like pure functions and unpredictable code like doing I/O can be treated the same. both can compose well too. effectively make impure code pure.