From: dsorokin on
Hi!

I’m glad to announce my new project cl-monad-macros which is available
by the following link: http://common-lisp.net/project/cl-monad-macros/
Here I invented monad macros. This is a small set of macros that allow
the programmer familiar with Haskell to use the existent and create
new monads in Common Lisp. There are a few predefined monad macros
including such complex cases as the monad transformer macros. Also I
tried to create a syntax that would be intuitive for the Lisp
programmers. There is an alternative to the famous do-notation from
Haskell. This alternative is similar to the standard LET* and PROGN
operators.

Even if you don’t plan to use the monad macros, I guess that the List
monad can be still interesting as it allows us to use easily and
demonstrably a List Comprehension in CL.

Regards
David Sorokin
From: Pascal Costanza on
On 21/01/2010 19:49, namekuseijin wrote:
> dsorokin escreveu:
>> Hi!
>>
>> I�m glad to announce my new project cl-monad-macros which is available
>> by the following link: http://common-lisp.net/project/cl-monad-macros/
>> Here I invented monad macros. This is a small set of macros that allow
>> the programmer familiar with Haskell to use the existent and create
>> new monads in Common Lisp. There are a few predefined monad macros
>> including such complex cases as the monad transformer macros. Also I
>> tried to create a syntax that would be intuitive for the Lisp
>> programmers. There is an alternative to the famous do-notation from
>> Haskell. This alternative is similar to the standard LET* and PROGN
>> operators.
>>
>> Even if you don�t plan to use the monad macros, I guess that the List
>> monad can be still interesting as it allows us to use easily and
>> demonstrably a List Comprehension in CL.
>
> why do you need monads in a language with full state? I'd rather have
> lazy Lisp instead.

There is no contradiction there. Feel free to publish your own library
for lazy computations.


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Drew Crampsie on
namekuseijin <namekuseijin(a)gmail.com> writes:
>
> why do you need monads in a language with full state?

Why do you need objects in a language with closures?

Monadic tranformations have proved useful in CL for me in two distinct
places... continuations and parsing using combinators. This has nothing
to do with stateful vs functional, and everything do to with
transforming code.

> I'd rather have lazy Lisp instead.

Why not both? The two concepts are completely orthagonal... I use
lazyness and monads in lisp all the time because they are useful
tools.

Cheers,

drewc






From: Kaz Kylheku on
On 2010-01-21, dsorokin <david.sorokin(a)gmail.com> wrote:
> Hi!
>
> I'm glad to announce my new project cl-monad-macros which is available
> by the following link: http://common-lisp.net/project/cl-monad-macros/

Look here.

http://paste.lisp.org/display/71196
From: Kaz Kylheku on
On 2010-01-21, Kaz Kylheku <kkylheku(a)gmail.com> wrote:
> On 2010-01-21, dsorokin <david.sorokin(a)gmail.com> wrote:
>> Hi!
>>
>> I'm glad to announce my new project cl-monad-macros which is available
>> by the following link: http://common-lisp.net/project/cl-monad-macros/
>
> Look here.
>
> http://paste.lisp.org/display/71196

From the ``cl-monad-macros'' doc:

``I tried to introduce the monads in the Lisp Way. I know that there were other
attempts. They are mainly based on using generic functions that allow the
programmer to write a polymorphic code but at the cost of some lost of the
performance. My approach, on the contrary, allows the Lisp compiler to generate
an efficient code but it lacks some flexibility.''

This is misleading. I used generic functions to make the implementation
concise, but CLOS is not used in an essential way and the define-monad macro
hides the fact that CLOS is being used.

Though the implementation uses CLOS, the class of the monad is hard-wired at
macro-expansion time to, which could be easily staged into compile time.

E.g.:

;;;
;;; State transformer monad, with operations expressed using comprehensions
;;; over the identity monad, featuring multiple-value binding.
;;;
(define-monad state-xform-monad
:comprehension state-xform-comp
:map ((f)
(lambda (xformer)
(lambda (s)
(identity-comp (values (funcall f x) new-state)
((x new-state) (funcall xformer s))))))
:join ((nested-xformer)
(lambda (s)
(identity-comp (values x new-state)
((embedded-xformer intermediate-state)
(funcall nested-xformer s))
((x new-state)
(funcall embedded-xformer intermediate-state)))))
:unit ((x) (lambda (s) (values x s))))

Here, an association is formed between the symbol STATE-XFORM-MONAD and the
three functions. It's achieved internally using CLOS, by defining a class for
that symbol, a representative instance of that class, and then three methods.
When you use a comprehension macro like STATE-XFORM-COMP, it generates a call
to the COMPREHEND macro like this:

(COMPREHEND 'STATE-XFORM-MONAD ARGS ...)

This does indeed generate the code in a generic way; i.e. the generated code
fetches the representative CLOS instance for the STATE-XFORM-MONAD class and
uses it to do dispatch. But this is just a code generation choice that could
be changed. For instance, the macro could instead look up STATE-XFORM-MONAD in
a hash table and actually statically pull out the names of functions to
substitute into the generated code.