Last week I released a project with a monadic translator that needed to:
- work on sequences of expressions, arbitrarily nested
- generate Clojure code or stop and report the first error
- maintain a symbol table with easy access but not global state

The relevant code is here:
https://github.com/blancas/eisen/blob/master/src/main/clojure/blancas/eisen/trans.clj

The code uses a StateT monad transformer and Either monad wrapped in five 
API functions: ->left, ->right, get-se, modify-se, run-se. Functions report 
errors with (->left); function (->right) wraps good values. The macro 
(monad) corresponds to Haskell's do; it chains monadic values or 
short-circuits and propagates errors.


(defn trans-binop
  "Translates the application of a binary operator."
  [ast]
  (monad [x (trans-expr (:left ast))
          y (trans-expr (:right ast))]
    (let [f (-> ast :op :value str symbol)]
      (->right `(~f ~x ~y)))))


The symbol table is available through get-se and modify-se. A typical use 
case is to enter declared names, translate the expressions, then remove the 
names from the symbol table.

(defn trans-let
  "Translates a let expression."
  [{:keys [decls exprs]}]
  (let [env (map (comp symbol :name) decls)]
    (monad [_     (modify-se into env)
            decls (trans-bindings decls)
            exprs (trans-exprs exprs)
            _     (modify-se difference env)]
      (->right `(let [~@(apply concat decls)] ~@exprs)))))


To translate expressions in a sequence it uses the generic function (seqm); 
function (run-se) evaluates the resulting sequenced monads using an initial 
state "predefs". The result from (run-se) feeds (either) which evaluates to 
the first form on ->left and to the second on ->right.

(let [job (monad [v (seqm (map eval-ast coll))] (->right v))]
    (either [res (run-se job predefs)]
      {:ok false :error res}
      {:ok true :decls (map first res) :value (-> res last second)})))


On Monday, April 8, 2013 7:56:35 AM UTC-7, Carlos Galdino wrote:
>
> Hi,
>
> I've been reading about monads for the past couple of weeks and I think I 
> got the idea, but I still don't know when to use it since I don't have 
> enough experience with functional programming.
>
> So, I'd like to ask you guys if you can point me to some examples of 
> Monads usage "in the wild". Because I've seen a lot of simple examples but 
> not a real one, used in a library, etc.
>
> Does anyone know a good example of real world usage?
>
> Thanks in advance.
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to