Skip to content

Instantly share code, notes, and snippets.

@jebberjeb
Last active August 29, 2015 13:56
Show Gist options
  • Select an option

  • Save jebberjeb/8935872 to your computer and use it in GitHub Desktop.

Select an option

Save jebberjeb/8935872 to your computer and use it in GitHub Desktop.

State Monad

TL;DR I'll probably just use a macro

What

A structure which allows you to represent a computation as a sequence of steps. The monad allows you to decorate each step with additional processing rules.

  • Logging
  • IO
  • Error handling

Allows things like side-effects, IO, etc to be defined in a purely functional manner.

Why

But

[Do you really need them in Clojure?] (https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCYQtwIwAA&url=http%3A%2F%2Fwww.infoq.com%2Fpresentations%2FMacros-Monads&ei=guv6UqrZEefH0AHJjICACw&usg=AFQjCNHCXLKjyGgVoCRvJN-M7_h5tN2ISg&sig2=aK0kzDz-EYGuxd4YOZWPSQ&bvm=bv.61190604,d.dmQ)

Computation Pipeline

Let

  (let [a (step1)
        b (step2 a)
        c (step3 b)
       ...])

->> w/ lists

  (->> foos
       (map step1)
       (map step2)
       (map step3))

Both have difficulty requiring with try/catch or conditional logic to recover from errors at each step.

Functional Solution

  (->> foos
       (map step1)
       (map step2)
       (map (wrap-check-a step3))
       (map (wrap-check a step4))
       (map (wrap-check-b (wrap-check-a step5)))
       (map (wrap-check-b (wrap-check-a step6)))
       ...)
       
  (defn wrap-check-a [step] (fn [m] (if (:a m) (step m) m)))

Monadic Solution

  ;; MORE scaffolding
  (defmonad m-halt-error 
            m-bind (fn [state step m] (if (and (:check-a state) (not (:a m)) m (step m)))) ;; simplification
  ...)

  (defn ---must-have-a--- [state] (assoc state :check-a true) ;; alter monad state.

  ;; LESS clutter to core pipeline
  (with-monad m-halt-error
    (m-chain [step1
              step2
              ---must-have-a---
              step3
              step4
              ---must-have-b---
              step5
              step6
              ...]))

Pros

  • Gives you an imperative looking solution (w/ state).
  • Reduce clutter to core pipeline.
  • AOP.
  • Well-known [about].

Cons

  • Macros & other features in Clojure.
  • Cognative load.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment