-; Copyright 2008 (c) Meikel Brandmeyer.

-; Permission is hereby granted, free of charge, to any person obtaining a copy

-; of this software and associated documentation files (the "Software"), to deal

-; in the Software without restriction, including without limitation the rights

-; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

-; copies of the Software, and to permit persons to whom the Software is

-; furnished to do so, subject to the following conditions:

-; The above copyright notice and this permission notice shall be included in

-; all copies or substantial portions of the Software.

-; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

-; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

-; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

-; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

-; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

-; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

- `monad` is a small support library for Clojure_ which provides some of

- the infrastructure to handle monads. A monad is defined as a `struct-map`

- which contains the key `:monad`, which defines the type of the actual

- monad. This value is used as the dispatch value for the `bind` multimethod.

- `bind` is obviously dependent on the actual monad implementation.

- On application of monads are for example the parser combinators. Here

- the monads server as means to combine different parsers together to form

- new parsers. An example implementation for Clojure_ is „Parser_“ from the

- .. _Clojure: http://clojure.org

- .. _Parser: http://kotka.de/projects/clojure/parser.html")

-(clojure/in-ns 'de.kotka.monad)

-(clojure/refer 'clojure)

- `monad-structure` defines the basic structure of the monad supporting

- structure. The :monad key is the dispatch value for the `bind` multimethod.

- Whatever else is contained in the structure is completely up to the actual

- implementation and will not be touched by the functions of the monad library."}

- (create-struct :monad))

- (make-monad monad-type key value ...)

- `make-monad` creates a new monad structure and associates the :monad key

- with given monad-type. What the monad-type actually is, is up to the caller.

- This value will be used for dispatching in the `bind` multimethod.

- Any further key-value pairs will be associated with the map."

- (apply struct-map monad-structure :monad monad-type kvs))

- (bind monad (fn [result] ...)) : Monad a -> (a -> b)-> Monad b

- `bind` makes the value of the given monad available to a function.

- The function may act on the value, but it must return another monad.

- (Although this cannot be enforced in Clojure."}

- bind (fn [m f] (:monad m)))

- `let-bind` binds the result of the given monads to the given variables

- and executes the body in an implicit `do` block. How this done exactly

- depends on the actual monad. The `let-bind` body should again return a

- (let [[var monad & clauses] clauses]

- `(bind ~monad (fn [~var] ~@body))

- `(bind ~monad (fn [~var] (let-bind ~clauses ~@body))))))