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.
- 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
.
Leiningen:
[org.blancas/morph "0.1.0"]
Maven:
<dependency>
<groupId>org.blancas</groupId>
<artifactId>morph</artifactId>
<version>0.1.0</version>
</dependency>
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
'blancas.morph.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."
[op]
(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}
Morph is documented in the Wiki.
Browse the Codox Morph v0.1.0 API.
To generate the API docs (in the codox
directory):
lein doc
Copyright © 2013 Armando Blancas.
Licensed under the Eclipse Public License.