Skip to content
A Library of Morphisms: Monoids, Functors, and Monads
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Morph is a library of Haskell-style morphisms: monoids, functors, and monads. These constructs are helpful for designing programs that are purely functional and that encapsulate the boilerplate employed by many programming techniques.


  • Implementation based on protocols and data types.
  • Predefined monoids and functors; with support for Clojure collections.
  • Monads: Identity, Maybe, Either, Reader, Writer, State, Imperative.
  • Monad Transformers: MaybeT, EitherT, ReaderT, WriterT, StateT.
  • Support for curried functions.
  • Library of generic functions for the above constructs.
  • Sample code in src/main/resources.

These constructs have a reputation of being hard to explain and even harder to understand and to apply in everyday programming. I've made every effort to present them as regular techniques and idioms with practical benefits. Behind their strange or fancy names, these are just functions that work on data types.

An intuition of their behavior is all that's needed to take advantage of these functions; you may never need or want to write your own. I'm pleased with the power and simplicity these techniques have to offer and I hope you may find them useful as well.

Sample Usage

A simple expression evaluator uses the State monad; it can declare variables and clear the symbol table. Access to the symbol table is direct as if it were global, though all functions are pure.

(use '[blancas.morph core monads])

(def table {'DEG 57.295779 'E 2.718281 'PI 3.141592})

(declare run)

(defn calc
  "Evaluates and unboxes the operands; then applies the
   operator and returns the result as new state value."
  [op x y]
  (monad [a (run x) b (run y)]
    (state (op a b))))

(defn const
  "Returns a state value with a looked-up value or the given number."
  [x] (if (symbol? x) (gets x) (state x)))

(defn decl
  "Declares a variable as (var = val); value is used in-place."
  [x y] (>> (modify-state assoc x y) (state y)))

(defn clear
  "Clears the symbol table as (val %); value is used in-place."
  [x] (>> (put-state {}) (state x)))

(defn run
  "Dispatches on an expression or a single value."
  (if (list? op)
    (case (second op)
      + (calc + (first op) (last op))
      - (calc - (first op) (last op))
      * (calc * (first op) (last op))
      / (calc / (first op) (last op))
      = (decl   (first op) (last op))
      % (clear  (first op)))
    (const op)))

Now we evaluate some expressions with table as the initial state.

(eval-state (run '((9 / 3) + (2 * (PI - E)))) table)
;; 3.846622
(exec-state (run '((180 / (k = 30)) + (k * (PI - E)))) table)
;; {PI 3.141592, E 2.718281, DEG 57.295779, k 30}
(exec-state (run '(((180 %) / (k = 30)) + ((j = 5) * (k - j)))) table)
;; {j 5, k 30}



[org.blancas/morph "0.3.0"]



Changes for release 0.3.0:

  • Fixed slow, reflective calls by adding type hints.


Browse the whole change log.

Morph is documented in the Wiki.

Browse the Codox Morph v0.3.0 API.

To generate the API docs (in the codox directory):

lein doc


YourKit is kindly supporting open source projects with its full-featured Java Profiler.

YourKit, LLC is the creator of innovative and intelligent tools for profiling Java and .NET applications. Take a look at YourKit's leading software products:


Copyright © 2013 Armando Blancas.

Licensed under the Eclipse Public License.

You can’t perform that action at this time.