(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?
@lispyclouds sounds like this whole thing needs discussion of threading macros like ->
@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?
@worldsendless well its more from the idea of if we pass around containers of data than just raw values, we can "hide" things in them without changing the code around it. the code around it just cares about the container then. we pass a error or a value and mark the container accordingly and the code around reacts to it. Reduced is the error container.
@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?
@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.
@lispyclouds Thank you! I have learned.
@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.